39 bool tetgenio::load_node_call(FILE* infile,
int markers,
int uvflag,
42 char inputline[INPUTLINESIZE];
45 int firstnode, currentmarker;
46 int index, attribindex;
50 pointlist =
new REAL[numberofpoints * 3];
51 if (pointlist == (REAL *) NULL) {
52 terminatetetgen(NULL, 1);
54 if (numberofpointattributes > 0) {
55 pointattributelist =
new REAL[numberofpoints * numberofpointattributes];
56 if (pointattributelist == (REAL *) NULL) {
57 terminatetetgen(NULL, 1);
61 pointmarkerlist =
new int[numberofpoints];
62 if (pointmarkerlist == (
int *) NULL) {
63 terminatetetgen(NULL, 1);
67 pointparamlist =
new pointparam[numberofpoints];
68 if (pointparamlist == NULL) {
69 terminatetetgen(NULL, 1);
76 for (i = 0; i < numberofpoints; i++) {
77 stringptr = readnumberline(inputline, infile, infilename);
80 firstnode = (int) strtol (stringptr, &stringptr, 0);
81 if ((firstnode == 0) || (firstnode == 1)) {
82 firstnumber = firstnode;
85 stringptr = findnextnumber(stringptr);
87 if (*stringptr ==
'\0') {
88 printf(
"Error: Point %d has no x coordinate.\n", firstnumber + i);
91 x = (REAL) strtod(stringptr, &stringptr);
92 stringptr = findnextnumber(stringptr);
93 if (*stringptr ==
'\0') {
94 printf(
"Error: Point %d has no y coordinate.\n", firstnumber + i);
97 y = (REAL) strtod(stringptr, &stringptr);
99 stringptr = findnextnumber(stringptr);
100 if (*stringptr ==
'\0') {
101 printf(
"Error: Point %d has no z coordinate.\n", firstnumber + i);
104 z = (REAL) strtod(stringptr, &stringptr);
108 pointlist[index++] = x;
109 pointlist[index++] = y;
110 pointlist[index++] = z;
112 for (j = 0; j < numberofpointattributes; j++) {
113 stringptr = findnextnumber(stringptr);
114 if (*stringptr ==
'\0') {
117 attrib = (REAL) strtod(stringptr, &stringptr);
119 pointattributelist[attribindex++] = attrib;
123 stringptr = findnextnumber(stringptr);
124 if (*stringptr ==
'\0') {
127 currentmarker = (int) strtol (stringptr, &stringptr, 0);
129 pointmarkerlist[i] = currentmarker;
133 stringptr = findnextnumber(stringptr);
134 if (*stringptr ==
'\0') {
135 printf(
"Error: Point %d has no uv[0].\n", firstnumber + i);
138 pointparamlist[i].uv[0] = (REAL) strtod(stringptr, &stringptr);
139 stringptr = findnextnumber(stringptr);
140 if (*stringptr ==
'\0') {
141 printf(
"Error: Point %d has no uv[1].\n", firstnumber + i);
144 pointparamlist[i].uv[1] = (REAL) strtod(stringptr, &stringptr);
145 stringptr = findnextnumber(stringptr);
146 if (*stringptr ==
'\0') {
147 printf(
"Error: Point %d has no tag.\n", firstnumber + i);
150 pointparamlist[i].tag = (int) strtol (stringptr, &stringptr, 0);
151 stringptr = findnextnumber(stringptr);
152 if (*stringptr ==
'\0') {
153 printf(
"Error: Point %d has no type.\n", firstnumber + i);
156 pointparamlist[i].type = (int) strtol (stringptr, &stringptr, 0);
157 if ((pointparamlist[i].type < 0) || (pointparamlist[i].type > 2)) {
158 printf(
"Error: Point %d has an invalid type.\n", firstnumber + i);
163 if (i < numberofpoints) {
166 pointlist = (REAL *) NULL;
168 delete [] pointmarkerlist;
169 pointmarkerlist = (
int *) NULL;
171 if (numberofpointattributes > 0) {
172 delete [] pointattributelist;
173 pointattributelist = (REAL *) NULL;
176 delete [] pointparamlist;
177 pointparamlist = NULL;
191 bool tetgenio::load_node(
char* filebasename)
194 char innodefilename[FILENAMESIZE];
195 char inputline[INPUTLINESIZE];
202 strcpy(innodefilename, filebasename);
203 strcat(innodefilename,
".node");
206 infile = fopen(innodefilename,
"r");
207 if (infile == (FILE *) NULL) {
208 printf(
" Cannot access file %s.\n", innodefilename);
211 printf(
"Opening %s.\n", innodefilename);
215 numberofpointattributes = 0;
220 stringptr = readnumberline(inputline, infile, innodefilename);
222 stringptr = strstr(inputline,
"rbox");
223 if (stringptr == NULL) {
226 stringptr = inputline;
227 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
228 stringptr = findnextnumber(stringptr);
229 if (*stringptr !=
'\0') {
230 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
232 stringptr = findnextnumber(stringptr);
233 if (*stringptr !=
'\0') {
234 numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
236 stringptr = findnextnumber(stringptr);
237 if (*stringptr !=
'\0') {
238 markers = (int) strtol (stringptr, &stringptr, 0);
240 stringptr = findnextnumber(stringptr);
241 if (*stringptr !=
'\0') {
242 uvflag = (int) strtol (stringptr, &stringptr, 0);
246 stringptr = inputline;
248 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
250 stringptr = readnumberline(inputline, infile, innodefilename);
251 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
257 okflag = load_node_call(infile, markers, uvflag, innodefilename);
269 bool tetgenio::load_edge(
char* filebasename)
272 char inedgefilename[FILENAMESIZE];
273 char inputline[INPUTLINESIZE];
279 strcpy(inedgefilename, filebasename);
280 strcat(inedgefilename,
".edge");
282 infile = fopen(inedgefilename,
"r");
283 if (infile != (FILE *) NULL) {
284 printf(
"Opening %s.\n", inedgefilename);
291 stringptr = readnumberline(inputline, infile, inedgefilename);
292 numberofedges = (int) strtol (stringptr, &stringptr, 0);
293 if (numberofedges > 0) {
294 edgelist =
new int[numberofedges * 2];
295 if (edgelist == (
int *) NULL) {
296 terminatetetgen(NULL, 1);
298 stringptr = findnextnumber(stringptr);
299 if (*stringptr ==
'\0') {
302 markers = (int) strtol (stringptr, &stringptr, 0);
305 edgemarkerlist =
new int[numberofedges];
311 for (i = 0; i < numberofedges; i++) {
313 stringptr = readnumberline(inputline, infile, inedgefilename);
314 for (j = 0; j < 2; j++) {
315 stringptr = findnextnumber(stringptr);
316 if (*stringptr ==
'\0') {
317 printf(
"Error: Edge %d is missing vertex %d in %s.\n",
318 i + firstnumber, j + 1, inedgefilename);
319 terminatetetgen(NULL, 1);
321 corner = (int) strtol(stringptr, &stringptr, 0);
322 if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
323 printf(
"Error: Edge %d has an invalid vertex index.\n",
325 terminatetetgen(NULL, 1);
327 edgelist[index++] = corner;
329 if (numberofcorners == 10) {
331 stringptr = findnextnumber(stringptr);
335 stringptr = findnextnumber(stringptr);
336 edgemarkerlist[i] = (int) strtol(stringptr, &stringptr, 0);
350 bool tetgenio::load_face(
char* filebasename)
353 char infilename[FILENAMESIZE];
354 char inputline[INPUTLINESIZE];
361 strcpy(infilename, filebasename);
362 strcat(infilename,
".face");
364 infile = fopen(infilename,
"r");
365 if (infile != (FILE *) NULL) {
366 printf(
"Opening %s.\n", infilename);
372 stringptr = readnumberline(inputline, infile, infilename);
373 numberoftrifaces = (int) strtol (stringptr, &stringptr, 0);
374 stringptr = findnextnumber(stringptr);
377 stringptr = findnextnumber(stringptr);
379 if (*stringptr ==
'\0') {
382 markers = (int) strtol (stringptr, &stringptr, 0);
384 if (numberoftrifaces > 0) {
385 trifacelist =
new int[numberoftrifaces * 3];
386 if (trifacelist == (
int *) NULL) {
387 terminatetetgen(NULL, 1);
390 trifacemarkerlist =
new int[numberoftrifaces];
391 if (trifacemarkerlist == (
int *) NULL) {
392 terminatetetgen(NULL, 1);
399 for (i = 0; i < numberoftrifaces; i++) {
401 stringptr = readnumberline(inputline, infile, infilename);
402 for (j = 0; j < 3; j++) {
403 stringptr = findnextnumber(stringptr);
404 if (*stringptr ==
'\0') {
405 printf(
"Error: Face %d is missing vertex %d in %s.\n",
406 i + firstnumber, j + 1, infilename);
407 terminatetetgen(NULL, 1);
409 corner = (int) strtol(stringptr, &stringptr, 0);
410 if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
411 printf(
"Error: Face %d has an invalid vertex index.\n",
413 terminatetetgen(NULL, 1);
415 trifacelist[index++] = corner;
417 if (numberofcorners == 10) {
419 for (j = 0; j < 3; j++) {
420 stringptr = findnextnumber(stringptr);
425 stringptr = findnextnumber(stringptr);
426 if (*stringptr ==
'\0') {
429 attrib = (REAL) strtod(stringptr, &stringptr);
431 trifacemarkerlist[i] = (int) attrib;
446 bool tetgenio::load_tet(
char* filebasename)
449 char infilename[FILENAMESIZE];
450 char inputline[INPUTLINESIZE];
454 int index, attribindex;
457 strcpy(infilename, filebasename);
458 strcat(infilename,
".ele");
460 infile = fopen(infilename,
"r");
461 if (infile != (FILE *) NULL) {
462 printf(
"Opening %s.\n", infilename);
469 stringptr = readnumberline(inputline, infile, infilename);
470 numberoftetrahedra = (int) strtol (stringptr, &stringptr, 0);
471 if (numberoftetrahedra <= 0) {
472 printf(
"Error: Invalid number of tetrahedra.\n");
476 stringptr = findnextnumber(stringptr);
477 if (*stringptr ==
'\0') {
480 numberofcorners = (int) strtol(stringptr, &stringptr, 0);
482 stringptr = findnextnumber(stringptr);
483 if (*stringptr ==
'\0') {
484 numberoftetrahedronattributes = 0;
486 numberoftetrahedronattributes = (int) strtol(stringptr, &stringptr, 0);
488 if (numberofcorners != 4 && numberofcorners != 10) {
489 printf(
"Error: Wrong number of corners %d (should be 4 or 10).\n",
496 tetrahedronlist =
new int[numberoftetrahedra * numberofcorners];
497 if (tetrahedronlist == (
int *) NULL) {
498 terminatetetgen(NULL, 1);
501 if (numberoftetrahedronattributes > 0) {
502 tetrahedronattributelist =
new REAL[numberoftetrahedra *
503 numberoftetrahedronattributes];
504 if (tetrahedronattributelist == (REAL *) NULL) {
505 terminatetetgen(NULL, 1);
512 for (i = 0; i < numberoftetrahedra; i++) {
514 stringptr = readnumberline(inputline, infile, infilename);
515 for (j = 0; j < numberofcorners; j++) {
516 stringptr = findnextnumber(stringptr);
517 if (*stringptr ==
'\0') {
518 printf(
"Error: Tetrahedron %d is missing vertex %d in %s.\n",
519 i + firstnumber, j + 1, infilename);
520 terminatetetgen(NULL, 1);
522 corner = (int) strtol(stringptr, &stringptr, 0);
523 if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
524 printf(
"Error: Tetrahedron %d has an invalid vertex index.\n",
526 terminatetetgen(NULL, 1);
528 tetrahedronlist[index++] = corner;
531 for (j = 0; j < numberoftetrahedronattributes; j++) {
532 stringptr = findnextnumber(stringptr);
533 if (*stringptr ==
'\0') {
536 attrib = (REAL) strtod(stringptr, &stringptr);
538 tetrahedronattributelist[attribindex++] = attrib;
553 bool tetgenio::load_vol(
char* filebasename)
556 char inelefilename[FILENAMESIZE];
557 char infilename[FILENAMESIZE];
558 char inputline[INPUTLINESIZE];
564 strcpy(infilename, filebasename);
565 strcat(infilename,
".vol");
567 infile = fopen(infilename,
"r");
568 if (infile != (FILE *) NULL) {
569 printf(
"Opening %s.\n", infilename);
575 stringptr = readnumberline(inputline, infile, infilename);
576 volelements = (int) strtol (stringptr, &stringptr, 0);
577 if (volelements != numberoftetrahedra) {
578 strcpy(inelefilename, filebasename);
579 strcat(infilename,
".ele");
580 printf(
"Warning: %s and %s disagree on number of tetrahedra.\n",
581 inelefilename, infilename);
586 tetrahedronvolumelist =
new REAL[volelements];
587 if (tetrahedronvolumelist == (REAL *) NULL) {
588 terminatetetgen(NULL, 1);
592 for (i = 0; i < volelements; i++) {
593 stringptr = readnumberline(inputline, infile, infilename);
594 stringptr = findnextnumber(stringptr);
595 if (*stringptr ==
'\0') {
598 volume = (REAL) strtod(stringptr, &stringptr);
600 tetrahedronvolumelist[i] = volume;
615 bool tetgenio::load_var(
char* filebasename)
618 char varfilename[FILENAMESIZE];
619 char inputline[INPUTLINESIZE];
625 strcpy(varfilename, filebasename);
626 strcat(varfilename,
".var");
627 infile = fopen(varfilename,
"r");
628 if (infile != (FILE *) NULL) {
629 printf(
"Opening %s.\n", varfilename);
635 stringptr = readnumberline(inputline, infile, varfilename);
636 if (stringptr == NULL) {
641 if (*stringptr !=
'\0') {
642 numberoffacetconstraints = (int) strtol (stringptr, &stringptr, 0);
644 numberoffacetconstraints = 0;
646 if (numberoffacetconstraints > 0) {
648 facetconstraintlist =
new REAL[numberoffacetconstraints * 2];
650 for (i = 0; i < numberoffacetconstraints; i++) {
651 stringptr = readnumberline(inputline, infile, varfilename);
652 stringptr = findnextnumber(stringptr);
653 if (*stringptr ==
'\0') {
654 printf(
"Error: facet constraint %d has no facet marker.\n",
658 facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
660 stringptr = findnextnumber(stringptr);
661 if (*stringptr ==
'\0') {
662 printf(
"Error: facet constraint %d has no maximum area bound.\n",
666 facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
669 if (i < numberoffacetconstraints) {
677 stringptr = readnumberline(inputline, infile, varfilename);
678 if (stringptr == NULL) {
683 if (*stringptr !=
'\0') {
684 numberofsegmentconstraints = (int) strtol (stringptr, &stringptr, 0);
686 numberofsegmentconstraints = 0;
688 if (numberofsegmentconstraints > 0) {
690 segmentconstraintlist =
new REAL[numberofsegmentconstraints * 3];
692 for (i = 0; i < numberofsegmentconstraints; i++) {
693 stringptr = readnumberline(inputline, infile, varfilename);
694 stringptr = findnextnumber(stringptr);
695 if (*stringptr ==
'\0') {
696 printf(
"Error: segment constraint %d has no frist endpoint.\n",
700 segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
702 stringptr = findnextnumber(stringptr);
703 if (*stringptr ==
'\0') {
704 printf(
"Error: segment constraint %d has no second endpoint.\n",
708 segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
710 stringptr = findnextnumber(stringptr);
711 if (*stringptr ==
'\0') {
712 printf(
"Error: segment constraint %d has no maximum length bound.\n",
716 segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
719 if (i < numberofsegmentconstraints) {
736 bool tetgenio::load_mtr(
char* filebasename)
739 char mtrfilename[FILENAMESIZE];
740 char inputline[INPUTLINESIZE];
747 strcpy(mtrfilename, filebasename);
748 strcat(mtrfilename,
".mtr");
749 infile = fopen(mtrfilename,
"r");
750 if (infile != (FILE *) NULL) {
751 printf(
"Opening %s.\n", mtrfilename);
757 stringptr = readnumberline(inputline, infile, mtrfilename);
758 ptnum = (int) strtol (stringptr, &stringptr, 0);
759 if (ptnum != numberofpoints) {
760 printf(
" !! Point numbers are not equal. Ignored.\n");
765 stringptr = findnextnumber(stringptr);
766 if (*stringptr !=
'\0') {
767 numberofpointmtrs = (int) strtol (stringptr, &stringptr, 0);
769 if ((numberofpointmtrs != 1) && (numberofpointmtrs != 3) &&
770 (numberofpointmtrs != 6)) {
772 numberofpointmtrs = 0;
773 printf(
" !! Metric size does not match (1, 3, or 6). Ignored.\n");
779 pointmtrlist =
new REAL[numberofpoints * numberofpointmtrs];
780 if (pointmtrlist == (REAL *) NULL) {
781 terminatetetgen(NULL, 1);
784 for (i = 0; i < numberofpoints; i++) {
786 stringptr = readnumberline(inputline, infile, mtrfilename);
787 for (j = 0; j < numberofpointmtrs; j++) {
788 if (*stringptr ==
'\0') {
789 printf(
"Error: Metric %d is missing value #%d in %s.\n",
790 i + firstnumber, j + 1, mtrfilename);
791 terminatetetgen(NULL, 1);
793 mtr = (REAL) strtod(stringptr, &stringptr);
794 pointmtrlist[mtrindex++] = mtr;
795 stringptr = findnextnumber(stringptr);
809 bool tetgenio::load_poly(
char* filebasename)
812 char inpolyfilename[FILENAMESIZE];
813 char insmeshfilename[FILENAMESIZE];
814 char inputline[INPUTLINESIZE];
815 char *stringptr, *infilename;
816 int smesh, markers, uvflag, currentmarker;
821 strcpy(inpolyfilename, filebasename);
822 strcpy(insmeshfilename, filebasename);
823 strcat(inpolyfilename,
".poly");
824 strcat(insmeshfilename,
".smesh");
829 infile = fopen(inpolyfilename,
"r");
830 if (infile == (FILE *) NULL) {
832 infile = fopen(insmeshfilename,
"r");
833 if (infile == (FILE *) NULL) {
834 printf(
" Cannot access file %s and %s.\n",
835 inpolyfilename, insmeshfilename);
838 printf(
"Opening %s.\n", insmeshfilename);
839 infilename = insmeshfilename;
843 printf(
"Opening %s.\n", inpolyfilename);
844 infilename = inpolyfilename;
849 numberofpointattributes = 0;
855 stringptr = readnumberline(inputline, infile, infilename);
856 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
857 stringptr = findnextnumber(stringptr);
858 if (*stringptr !=
'\0') {
859 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
861 stringptr = findnextnumber(stringptr);
862 if (*stringptr !=
'\0') {
863 numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
865 stringptr = findnextnumber(stringptr);
866 if (*stringptr !=
'\0') {
867 markers = (int) strtol (stringptr, &stringptr, 0);
869 if (*stringptr !=
'\0') {
870 uvflag = (int) strtol (stringptr, &stringptr, 0);
873 if (numberofpoints > 0) {
875 if (!load_node_call(infile, markers, uvflag, infilename)) {
882 if (!load_node(filebasename)) {
888 if ((mesh_dim != 3) && (mesh_dim != 2)) {
889 printf(
"Input error: TetGen only works for 2D & 3D point sets.\n");
893 if (numberofpoints < (mesh_dim + 1)) {
894 printf(
"Input error: TetGen needs at least %d points.\n", mesh_dim + 1);
905 stringptr = readnumberline(inputline, infile, infilename);
906 if (stringptr == NULL) {
911 numberoffacets = (int) strtol (stringptr, &stringptr, 0);
912 if (numberoffacets <= 0) {
917 stringptr = findnextnumber(stringptr);
918 if (*stringptr ==
'\0') {
921 markers = (int) strtol (stringptr, &stringptr, 0);
925 facetlist =
new facet[numberoffacets];
927 facetmarkerlist =
new int[numberoffacets];
933 for (i = 1; i <= numberoffacets; i++) {
934 f = &(facetlist[i - 1]);
936 f->numberofholes = 0;
939 stringptr = readnumberline(inputline, infile, infilename);
940 f->numberofpolygons = (int) strtol (stringptr, &stringptr, 0);
941 stringptr = findnextnumber(stringptr);
942 if (*stringptr !=
'\0') {
943 f->numberofholes = (int) strtol (stringptr, &stringptr, 0);
945 stringptr = findnextnumber(stringptr);
946 if (*stringptr !=
'\0') {
947 currentmarker = (int) strtol(stringptr, &stringptr, 0);
953 facetmarkerlist[i - 1] = currentmarker;
956 if (f->numberofpolygons <= 0) {
957 printf(
"Error: Wrong number of polygon in %d facet.\n", i);
961 f->polygonlist =
new polygon[f->numberofpolygons];
963 for (j = 1; j <= f->numberofpolygons; j++) {
964 p = &(f->polygonlist[j - 1]);
967 stringptr = readnumberline(inputline, infile, infilename);
968 p->numberofvertices = (int) strtol(stringptr, &stringptr, 0);
969 if (p->numberofvertices < 1) {
970 printf(
"Error: Wrong polygon %d in facet %d\n", j, i);
974 p->vertexlist =
new int[p->numberofvertices];
976 for (k = 1; k <= p->numberofvertices; k++) {
977 stringptr = findnextnumber(stringptr);
978 if (*stringptr ==
'\0') {
981 stringptr = readnumberline(inputline, infile, infilename);
982 if (*stringptr ==
'\0') {
983 printf(
"Error: Missing %d endpoints of polygon %d in facet %d",
984 p->numberofvertices - k, j, i);
988 p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0);
991 if (j <= f->numberofpolygons) {
996 delete [] f->polygonlist;
998 f->numberofpolygons = j - 1;
1000 f->numberofholes = 0;
1004 if (f->numberofholes > 0) {
1006 f->holelist =
new REAL[f->numberofholes * 3];
1009 for (j = 1; j <= f->numberofholes; j++) {
1010 stringptr = readnumberline(inputline, infile, infilename);
1011 for (k = 1; k <= 3; k++) {
1012 stringptr = findnextnumber(stringptr);
1013 if (*stringptr ==
'\0') {
1014 printf(
"Error: Hole %d in facet %d has no coordinates", j, i);
1017 f->holelist[index++] = (REAL) strtod (stringptr, &stringptr);
1024 if (j <= f->numberofholes) {
1030 if (i <= numberoffacets) {
1032 numberoffacets = i - 1;
1038 for (i = 1; i <= numberoffacets; i++) {
1039 f = &(facetlist[i - 1]);
1043 f->numberofpolygons = 1;
1044 f->polygonlist =
new polygon[f->numberofpolygons];
1045 p = &(f->polygonlist[0]);
1048 stringptr = readnumberline(inputline, infile, insmeshfilename);
1049 p->numberofvertices = (int) strtol (stringptr, &stringptr, 0);
1050 if (p->numberofvertices < 1) {
1051 printf(
"Error: Wrong number of vertex in facet %d\n", i);
1055 p->vertexlist =
new int[p->numberofvertices];
1056 for (k = 1; k <= p->numberofvertices; k++) {
1057 stringptr = findnextnumber(stringptr);
1058 if (*stringptr ==
'\0') {
1061 stringptr = readnumberline(inputline, infile, infilename);
1062 if (*stringptr ==
'\0') {
1063 printf(
"Error: Missing %d endpoints in facet %d",
1064 p->numberofvertices - k, i);
1068 p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0);
1070 if (k <= p->numberofvertices) {
1076 stringptr = findnextnumber(stringptr);
1077 if (*stringptr ==
'\0') {
1080 currentmarker = (int) strtol(stringptr, &stringptr, 0);
1082 facetmarkerlist[i - 1] = currentmarker;
1085 if (i <= numberoffacets) {
1087 numberoffacets = i - 1;
1094 stringptr = readnumberline(inputline, infile, infilename);
1095 if (stringptr == NULL) {
1100 if (*stringptr !=
'\0') {
1101 numberofholes = (int) strtol (stringptr, &stringptr, 0);
1105 if (numberofholes > 0) {
1107 holelist =
new REAL[numberofholes * 3];
1108 for (i = 0; i < 3 * numberofholes; i += 3) {
1109 stringptr = readnumberline(inputline, infile, infilename);
1110 stringptr = findnextnumber(stringptr);
1111 if (*stringptr ==
'\0') {
1112 printf(
"Error: Hole %d has no x coord.\n", firstnumber + (i / 3));
1115 holelist[i] = (REAL) strtod(stringptr, &stringptr);
1117 stringptr = findnextnumber(stringptr);
1118 if (*stringptr ==
'\0') {
1119 printf(
"Error: Hole %d has no y coord.\n", firstnumber + (i / 3));
1122 holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
1124 stringptr = findnextnumber(stringptr);
1125 if (*stringptr ==
'\0') {
1126 printf(
"Error: Hole %d has no z coord.\n", firstnumber + (i / 3));
1129 holelist[i + 2] = (REAL) strtod(stringptr, &stringptr);
1132 if (i < 3 * numberofholes) {
1141 stringptr = readnumberline(inputline, infile, NULL);
1142 if (stringptr != (
char *) NULL && *stringptr !=
'\0') {
1143 numberofregions = (int) strtol (stringptr, &stringptr, 0);
1145 numberofregions = 0;
1147 if (numberofregions > 0) {
1149 regionlist =
new REAL[numberofregions * 5];
1151 for (i = 0; i < numberofregions; i++) {
1152 stringptr = readnumberline(inputline, infile, infilename);
1153 stringptr = findnextnumber(stringptr);
1154 if (*stringptr ==
'\0') {
1155 printf(
"Error: Region %d has no x coordinate.\n", firstnumber + i);
1158 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
1160 stringptr = findnextnumber(stringptr);
1161 if (*stringptr ==
'\0') {
1162 printf(
"Error: Region %d has no y coordinate.\n", firstnumber + i);
1165 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
1167 stringptr = findnextnumber(stringptr);
1168 if (*stringptr ==
'\0') {
1169 printf(
"Error: Region %d has no z coordinate.\n", firstnumber + i);
1172 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
1174 stringptr = findnextnumber(stringptr);
1175 if (*stringptr ==
'\0') {
1176 printf(
"Error: Region %d has no region attrib.\n", firstnumber + i);
1179 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
1181 stringptr = findnextnumber(stringptr);
1182 if (*stringptr ==
'\0') {
1183 regionlist[index] = regionlist[index - 1];
1185 regionlist[index] = (REAL) strtod(stringptr, &stringptr);
1189 if (i < numberofregions) {
1213 bool tetgenio::load_off(
char* filebasename)
1218 char infilename[FILENAMESIZE];
1219 char buffer[INPUTLINESIZE];
1222 int nverts = 0, iverts = 0;
1223 int nfaces = 0, ifaces = 0;
1225 int line_count = 0, i;
1229 int smallestidx = 0;
1231 strncpy(infilename, filebasename, 1024 - 1);
1232 infilename[FILENAMESIZE - 1] =
'\0';
1233 if (infilename[0] ==
'\0') {
1234 printf(
"Error: No filename.\n");
1237 if (strcmp(&infilename[strlen(infilename) - 4],
".off") != 0) {
1238 strcat(infilename,
".off");
1241 if (!(fp = fopen(infilename,
"r"))) {
1242 printf(
" Unable to open file %s\n", infilename);
1245 printf(
"Opening %s.\n", infilename);
1247 while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
1251 bufferp = strstr(bufferp,
"OFF");
1252 if (bufferp != NULL) {
1254 bufferp = findnextnumber(bufferp);
1255 if (*bufferp ==
'\0') {
1257 bufferp = readline(buffer, fp, &line_count);
1259 if ((sscanf(bufferp,
"%d%d%d", &nverts, &nfaces, &nedges) != 3)
1261 printf(
"Syntax error reading header on line %d in file %s\n",
1262 line_count, infilename);
1268 numberofpoints = nverts;
1269 pointlist =
new REAL[nverts * 3];
1270 smallestidx = nverts + 1;
1273 numberoffacets = nfaces;
1277 }
else if (iverts < nverts) {
1279 coord = &pointlist[iverts * 3];
1280 for (i = 0; i < 3; i++) {
1281 if (*bufferp ==
'\0') {
1282 printf(
"Syntax error reading vertex coords on line %d in file %s\n",
1283 line_count, infilename);
1287 coord[i] = (REAL) strtod(bufferp, &bufferp);
1288 bufferp = findnextnumber(bufferp);
1291 }
else if (ifaces < nfaces) {
1293 f = &facetlist[ifaces];
1296 f->numberofpolygons = 1;
1298 p = &f->polygonlist[0];
1301 p->numberofvertices = (int) strtol(bufferp, &bufferp, 0);
1302 if (p->numberofvertices == 0) {
1303 printf(
"Syntax error reading polygon on line %d in file %s\n",
1304 line_count, infilename);
1309 p->vertexlist =
new int[p->numberofvertices];
1310 for (i = 0; i < p->numberofvertices; i++) {
1311 bufferp = findnextnumber(bufferp);
1312 if (*bufferp ==
'\0') {
1313 printf(
"Syntax error reading polygon on line %d in file %s\n",
1314 line_count, infilename);
1318 p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0);
1320 if (p->vertexlist[i] < smallestidx) {
1321 smallestidx = p->vertexlist[i];
1327 printf(
"Found extra text starting at line %d in file %s\n", line_count,
1337 if (smallestidx == 0) {
1339 }
else if (smallestidx == 1) {
1342 printf(
"A wrong smallest index (%d) was detected in file %s\n",
1343 smallestidx, infilename);
1347 if (iverts != nverts) {
1348 printf(
"Expected %d vertices, but read only %d vertices in file %s\n",
1349 nverts, iverts, infilename);
1352 if (ifaces != nfaces) {
1353 printf(
"Expected %d faces, but read only %d faces in file %s\n",
1354 nfaces, ifaces, infilename);
1375 bool tetgenio::load_ply(
char* filebasename)
1380 char infilename[FILENAMESIZE];
1381 char buffer[INPUTLINESIZE];
1382 char *bufferp, *str;
1384 int endheader = 0, format = 0;
1385 int nverts = 0, iverts = 0;
1386 int nfaces = 0, ifaces = 0;
1387 int line_count = 0, i;
1391 int smallestidx = 0;
1393 strncpy(infilename, filebasename, FILENAMESIZE - 1);
1394 infilename[FILENAMESIZE - 1] =
'\0';
1395 if (infilename[0] ==
'\0') {
1396 printf(
"Error: No filename.\n");
1399 if (strcmp(&infilename[strlen(infilename) - 4],
".ply") != 0) {
1400 strcat(infilename,
".ply");
1403 if (!(fp = fopen(infilename,
"r"))) {
1404 printf(
"Error: Unable to open file %s\n", infilename);
1407 printf(
"Opening %s.\n", infilename);
1409 while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
1412 str = strstr(bufferp,
"end_header");
1414 if (!str) str = strstr(bufferp,
"End_header");
1415 if (!str) str = strstr(bufferp,
"End_Header");
1422 if (nverts == 0 || nfaces == 0) {
1424 str = strstr(bufferp,
"element");
1425 if (!str) str = strstr(bufferp,
"Element");
1427 bufferp = findnextfield(str);
1428 if (*bufferp ==
'\0') {
1429 printf(
"Syntax error reading element type on line%d in file %s\n",
1430 line_count, infilename);
1436 str = strstr(bufferp,
"vertex");
1437 if (!str) str = strstr(bufferp,
"Vertex");
1439 bufferp = findnextnumber(str);
1440 if (*bufferp ==
'\0') {
1441 printf(
"Syntax error reading vertex number on line");
1442 printf(
" %d in file %s\n", line_count, infilename);
1446 nverts = (int) strtol(bufferp, &bufferp, 0);
1449 numberofpoints = nverts;
1450 pointlist =
new REAL[nverts * 3];
1451 smallestidx = nverts + 1;
1457 str = strstr(bufferp,
"face");
1458 if (!str) str = strstr(bufferp,
"Face");
1460 bufferp = findnextnumber(str);
1461 if (*bufferp ==
'\0') {
1462 printf(
"Syntax error reading face number on line");
1463 printf(
" %d in file %s\n", line_count, infilename);
1467 nfaces = (int) strtol(bufferp, &bufferp, 0);
1470 numberoffacets = nfaces;
1479 str = strstr(bufferp,
"format");
1480 if (!str) str = strstr(bufferp,
"Format");
1483 bufferp = findnextfield(str);
1485 str = strstr(bufferp,
"ascii");
1486 if (!str) str = strstr(bufferp,
"ASCII");
1488 printf(
"This routine only reads ascii format of ply files.\n");
1489 printf(
"Hint: You can convert the binary to ascii format by\n");
1490 printf(
" using the provided ply tools:\n");
1491 printf(
" ply2ascii < %s > ascii_%s\n", infilename, infilename);
1497 }
else if (iverts < nverts) {
1499 coord = &pointlist[iverts * 3];
1500 for (i = 0; i < 3; i++) {
1501 if (*bufferp ==
'\0') {
1502 printf(
"Syntax error reading vertex coords on line %d in file %s\n",
1503 line_count, infilename);
1507 coord[i] = (REAL) strtod(bufferp, &bufferp);
1508 bufferp = findnextnumber(bufferp);
1511 }
else if (ifaces < nfaces) {
1513 f = &facetlist[ifaces];
1516 f->numberofpolygons = 1;
1518 p = &f->polygonlist[0];
1521 p->numberofvertices = (int) strtol(bufferp, &bufferp, 0);
1522 if (p->numberofvertices == 0) {
1523 printf(
"Syntax error reading polygon on line %d in file %s\n",
1524 line_count, infilename);
1529 p->vertexlist =
new int[p->numberofvertices];
1530 for (i = 0; i < p->numberofvertices; i++) {
1531 bufferp = findnextnumber(bufferp);
1532 if (*bufferp ==
'\0') {
1533 printf(
"Syntax error reading polygon on line %d in file %s\n",
1534 line_count, infilename);
1538 p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0);
1539 if (p->vertexlist[i] < smallestidx) {
1540 smallestidx = p->vertexlist[i];
1546 printf(
"Found extra text starting at line %d in file %s\n", line_count,
1556 if (smallestidx == 0) {
1558 }
else if (smallestidx == 1) {
1561 printf(
"A wrong smallest index (%d) was detected in file %s\n",
1562 smallestidx, infilename);
1566 if (iverts != nverts) {
1567 printf(
"Expected %d vertices, but read only %d vertices in file %s\n",
1568 nverts, iverts, infilename);
1571 if (ifaces != nfaces) {
1572 printf(
"Expected %d faces, but read only %d faces in file %s\n",
1573 nfaces, ifaces, infilename);
1594 void SwapBytes(
char *array,
int size,
int n)
1596 char *x =
new char[size];
1597 for(
int i = 0; i < n; i++) {
1598 char *a = &array[i * size];
1600 for(
int c = 0; c < size; c++)
1601 a[size - 1 - c] = x[c];
1606 bool tetgenio::load_stl(
char* filebasename)
1612 char infilename[FILENAMESIZE];
1613 char buffer[INPUTLINESIZE];
1614 char *bufferp, *str;
1617 int nverts = 0, iverts = 0;
1619 int line_count = 0, i;
1621 strncpy(infilename, filebasename, FILENAMESIZE - 1);
1622 infilename[FILENAMESIZE - 1] =
'\0';
1623 if (infilename[0] ==
'\0') {
1624 printf(
"Error: No filename.\n");
1627 if (strcmp(&infilename[strlen(infilename) - 4],
".stl") != 0) {
1628 strcat(infilename,
".stl");
1631 if (!(fp = fopen(infilename,
"rb"))) {
1632 printf(
"Error: Unable to open file %s\n", infilename);
1635 printf(
"Opening %s.\n", infilename);
1638 if(!fgets(buffer,
sizeof(buffer), fp)){ fclose(fp);
return 0; }
1639 bool binary = strncmp(buffer,
"solid", 5) && strncmp(buffer,
"SOLID", 5);
1646 while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
1651 bufferp = strstr(bufferp,
"solid");
1652 if (bufferp != NULL) {
1659 bufferp = strstr(bufferp,
"endsolid");
1660 if (bufferp != NULL) {
1665 bufferp = strstr(bufferp,
"vertex");
1666 if (bufferp != NULL) {
1667 plist->newindex((
void **) &coord);
1668 for (i = 0; i < 3; i++) {
1669 bufferp = findnextnumber(bufferp);
1670 if (*bufferp ==
'\0') {
1671 printf(
"Syntax error reading vertex coords on line %d\n",
1677 coord[i] = (REAL) strtod(bufferp, &bufferp);
1689 if(!fread(header,
sizeof(
char), 80, fp))
break;
1690 unsigned int nfacets = 0;
1691 size_t ret = fread(&nfacets,
sizeof(
unsigned int), 1, fp);
1693 if(nfacets > 100000000){
1696 SwapBytes((
char*)&nfacets,
sizeof(
unsigned int), 1);
1700 char *data =
new char[nfacets * 50 *
sizeof(char)];
1701 ret = fread(data,
sizeof(
char), nfacets * 50, fp);
1702 if(ret == nfacets * 50){
1703 for(
unsigned int i = 0; i < nfacets; i++) {
1704 float *xyz = (
float *)&data[i * 50 *
sizeof(
char)];
1705 if(swap) SwapBytes((
char*)xyz,
sizeof(
float), 12);
1706 for(
int j = 0; j < 3; j++){
1710 plist->newindex((
void **) &coord);
1711 coord[0] = xyz[3 + 3 * j];
1712 coord[1] = xyz[3 + 3 * j + 1];
1713 coord[2] = xyz[3 + 3 * j + 2];
1724 nverts = (int) plist->objects;
1726 if (nverts == 0 || (nverts % 3 != 0)) {
1727 printf(
"Error: Wrong number of vertices in file %s.\n", infilename);
1731 numberofpoints = nverts;
1732 pointlist =
new REAL[nverts * 3];
1733 for (i = 0; i < nverts; i++) {
1734 coord = (
double *) fastlookup(plist, i);
1736 pointlist[iverts] = (REAL) coord[0];
1737 pointlist[iverts + 1] = (REAL) coord[1];
1738 pointlist[iverts + 2] = (REAL) coord[2];
1741 nfaces = (int) (nverts / 3);
1742 numberoffacets = nfaces;
1747 iverts = firstnumber;
1748 for (i = 0; i < nfaces; i++) {
1752 f->numberofpolygons = 1;
1754 p = &f->polygonlist[0];
1757 p->numberofvertices = 3;
1758 p->vertexlist =
new int[p->numberofvertices];
1759 p->vertexlist[0] = iverts;
1760 p->vertexlist[1] = iverts + 1;
1761 p->vertexlist[2] = iverts + 2;
1778 bool tetgenio::load_medit(
char* filebasename,
int istetmesh)
1783 char infilename[FILENAMESIZE];
1784 char buffer[INPUTLINESIZE];
1785 char *bufferp, *str;
1797 int smallestidx = 0;
1799 strncpy(infilename, filebasename, FILENAMESIZE - 1);
1800 infilename[FILENAMESIZE - 1] =
'\0';
1801 if (infilename[0] ==
'\0') {
1802 printf(
"Error: No filename.\n");
1805 if (strcmp(&infilename[strlen(infilename) - 5],
".mesh") != 0) {
1806 strcat(infilename,
".mesh");
1809 if (!(fp = fopen(infilename,
"r"))) {
1810 printf(
"Error: Unable to open file %s\n", infilename);
1813 printf(
"Opening %s.\n", infilename);
1815 while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
1816 if (*bufferp ==
'#')
continue;
1817 if (dimension == 0) {
1819 str = strstr(bufferp,
"Dimension");
1820 if (!str) str = strstr(bufferp,
"dimension");
1821 if (!str) str = strstr(bufferp,
"DIMENSION");
1824 bufferp = findnextnumber(str);
1825 if (*bufferp ==
'\0') {
1827 bufferp = readline(buffer, fp, &line_count);
1829 dimension = (int) strtol(bufferp, &bufferp, 0);
1830 if (dimension != 2 && dimension != 3) {
1831 printf(
"Unknown dimension in file on line %d in file %s\n",
1832 line_count, infilename);
1836 mesh_dim = dimension;
1841 str = strstr(bufferp,
"Vertices");
1842 if (!str) str = strstr(bufferp,
"vertices");
1843 if (!str) str = strstr(bufferp,
"VERTICES");
1846 bufferp = findnextnumber(str);
1847 if (*bufferp ==
'\0') {
1849 bufferp = readline(buffer, fp, &line_count);
1851 nverts = (int) strtol(bufferp, &bufferp, 0);
1853 smallestidx = nverts + 1;
1856 numberofpoints = nverts;
1857 pointlist =
new REAL[nverts * 3];
1860 for (i = 0; i < nverts; i++) {
1861 bufferp = readline(buffer, fp, &line_count);
1862 if (bufferp == NULL) {
1863 printf(
"Unexpected end of file on line %d in file %s\n",
1864 line_count, infilename);
1869 coord = &pointlist[i * 3];
1870 for (j = 0; j < 3; j++) {
1871 if (*bufferp ==
'\0') {
1872 printf(
"Syntax error reading vertex coords on line");
1873 printf(
" %d in file %s\n", line_count, infilename);
1877 if ((j < 2) || (dimension == 3)) {
1878 coord[j] = (REAL) strtod(bufferp, &bufferp);
1882 bufferp = findnextnumber(bufferp);
1891 str = strstr(bufferp,
"Tetrahedra");
1892 if (!str) str = strstr(bufferp,
"tetrahedra");
1893 if (!str) str = strstr(bufferp,
"TETRAHEDRA");
1899 bufferp = findnextnumber(str);
1900 if (*bufferp ==
'\0') {
1902 bufferp = readline(buffer, fp, &line_count);
1904 ntets = strtol(bufferp, &bufferp, 0);
1907 numberoftetrahedra = ntets;
1908 numberofcorners = 4;
1909 numberoftetrahedronattributes = 1;
1910 tetrahedronlist =
new int[ntets * 4];
1911 tetrahedronattributelist =
new REAL[ntets];
1915 for (i = 0; i < numberoftetrahedra; i++) {
1916 plist = &(tetrahedronlist[i * 4]);
1917 bufferp = readline(buffer, fp, &line_count);
1918 if (bufferp == NULL) {
1919 printf(
"Unexpected end of file on line %d in file %s\n",
1920 line_count, infilename);
1925 for (j = 0; j < corners; j++) {
1926 if (*bufferp ==
'\0') {
1927 printf(
"Syntax error reading face on line %d in file %s\n",
1928 line_count, infilename);
1932 plist[j] = (int) strtol(bufferp, &bufferp, 0);
1934 if (plist[j] < smallestidx) smallestidx = plist[j];
1935 bufferp = findnextnumber(bufferp);
1938 tetrahedronattributelist[i] = 0;
1939 if (*bufferp !=
'\0') {
1940 tetrahedronattributelist[i] = (REAL) strtol(bufferp, &bufferp, 0);
1947 str = strstr(bufferp,
"Triangles");
1948 if (!str) str = strstr(bufferp,
"triangles");
1949 if (!str) str = strstr(bufferp,
"TRIANGLES");
1953 str = strstr(bufferp,
"Quadrilaterals");
1954 if (!str) str = strstr(bufferp,
"quadrilaterals");
1955 if (!str) str = strstr(bufferp,
"QUADRILATERALS");
1960 if (corners == 3 || corners == 4) {
1962 bufferp = findnextnumber(str);
1963 if (*bufferp ==
'\0') {
1965 bufferp = readline(buffer, fp, &line_count);
1967 nfaces = strtol(bufferp, &bufferp, 0);
1972 if (numberoffacets > 0) {
1976 tmpfmlist =
new int[numberoffacets + nfaces];
1978 for (i = 0; i < numberoffacets; i++) {
1982 tmpfmlist[i] = facetmarkerlist[i];
1985 delete [] facetlist;
1986 delete [] facetmarkerlist;
1988 facetlist = tmpflist;
1989 facetmarkerlist = tmpfmlist;
1993 facetmarkerlist =
new int[nfaces];
1998 numberoftrifaces = nfaces;
1999 trifacelist =
new int[nfaces * 3];
2000 trifacemarkerlist =
new int[nfaces];
2006 for (i = numberoffacets; i < numberoffacets + nfaces; i++) {
2007 bufferp = readline(buffer, fp, &line_count);
2008 if (bufferp == NULL) {
2009 printf(
"Unexpected end of file on line %d in file %s\n",
2010 line_count, infilename);
2017 f->numberofpolygons = 1;
2019 p = &f->polygonlist[0];
2021 p->numberofvertices = corners;
2023 p->vertexlist =
new int[p->numberofvertices];
2025 for (j = 0; j < corners; j++) {
2026 if (*bufferp ==
'\0') {
2027 printf(
"Syntax error reading face on line %d in file %s\n",
2028 line_count, infilename);
2032 p->vertexlist[j] = (int) strtol(bufferp, &bufferp, 0);
2034 if (p->vertexlist[j] < smallestidx) {
2035 smallestidx = p->vertexlist[j];
2037 bufferp = findnextnumber(bufferp);
2040 facetmarkerlist[i] = 0;
2041 if (*bufferp !=
'\0') {
2042 facetmarkerlist[i] = (int) strtol(bufferp, &bufferp, 0);
2046 numberoffacets += nfaces;
2051 for (i = 0; i < numberoftrifaces; i++) {
2052 plist = &(trifacelist[i * 3]);
2053 bufferp = readline(buffer, fp, &line_count);
2054 if (bufferp == NULL) {
2055 printf(
"Unexpected end of file on line %d in file %s\n",
2056 line_count, infilename);
2061 for (j = 0; j < corners; j++) {
2062 if (*bufferp ==
'\0') {
2063 printf(
"Syntax error reading face on line %d in file %s\n",
2064 line_count, infilename);
2068 plist[j] = (int) strtol(bufferp, &bufferp, 0);
2070 if (plist[j] < smallestidx) {
2071 smallestidx = plist[j];
2073 bufferp = findnextnumber(bufferp);
2076 trifacemarkerlist[i] = 0;
2077 if (*bufferp !=
'\0') {
2078 trifacemarkerlist[i] = (int) strtol(bufferp, &bufferp, 0);
2091 if (smallestidx == 0) {
2093 }
else if (smallestidx == 1) {
2096 printf(
"A wrong smallest index (%d) was detected in file %s\n",
2097 smallestidx, infilename);
2115 void swapBytes(
unsigned char* var,
int size)
2122 c = var[i]; var[i] = var[j]; var[j] = c;
2127 bool testIsBigEndian()
2129 short word = 0x4321;
2130 if((*(
char *)& word) != 0x21)
2136 bool tetgenio::load_vtk(
char* filebasename)
2141 char infilename[FILENAMESIZE];
2142 char line[INPUTLINESIZE];
2143 char mode[128],
id[256], fmt[64];
2155 bool ImALittleEndian = !testIsBigEndian();
2157 int smallestidx = 0;
2159 strncpy(infilename, filebasename, FILENAMESIZE - 1);
2160 infilename[FILENAMESIZE - 1] =
'\0';
2161 if (infilename[0] ==
'\0') {
2162 printf(
"Error: No filename.\n");
2165 if (strcmp(&infilename[strlen(infilename) - 4],
".vtk") != 0) {
2166 strcat(infilename,
".vtk");
2168 if (!(fp = fopen(infilename,
"r"))) {
2169 printf(
"Error: Unable to open file %s\n", infilename);
2172 printf(
"Opening %s.\n", infilename);
2176 strcpy(mode,
"BINARY");
2178 while((bufferp = readline(line, fp, &line_count)) != NULL) {
2179 if(strlen(line) == 0)
continue;
2181 if(line[0] ==
'#' || line[0]==
'\n' || line[0] == 10 || line[0] == 13 ||
2182 line[0] == 32)
continue;
2184 sscanf(line,
"%s",
id);
2185 if(!strcmp(
id,
"ASCII")) {
2186 strcpy(mode,
"ASCII");
2189 if(!strcmp(
id,
"POINTS")) {
2190 sscanf(line,
"%s %d %s",
id, &nverts, fmt);
2192 numberofpoints = nverts;
2193 pointlist =
new REAL[nverts * 3];
2194 smallestidx = nverts + 1;
2197 if(!strcmp(mode,
"BINARY")) {
2198 for(i = 0; i < nverts; i++) {
2199 coord = &pointlist[i * 3];
2200 if(!strcmp(fmt,
"double")) {
2201 fread((
char*)(&(coord[0])),
sizeof(
double), 1, fp);
2202 fread((
char*)(&(coord[1])),
sizeof(
double), 1, fp);
2203 fread((
char*)(&(coord[2])),
sizeof(
double), 1, fp);
2204 if(ImALittleEndian){
2205 swapBytes((
unsigned char *) &(coord[0]),
sizeof(coord[0]));
2206 swapBytes((
unsigned char *) &(coord[1]),
sizeof(coord[1]));
2207 swapBytes((
unsigned char *) &(coord[2]),
sizeof(coord[2]));
2209 }
else if(!strcmp(fmt,
"float")) {
2210 fread((
char*)(&_x),
sizeof(
float), 1, fp);
2211 fread((
char*)(&_y),
sizeof(
float), 1, fp);
2212 fread((
char*)(&_z),
sizeof(
float), 1, fp);
2213 if(ImALittleEndian){
2214 swapBytes((
unsigned char *) &_x,
sizeof(_x));
2215 swapBytes((
unsigned char *) &_y,
sizeof(_y));
2216 swapBytes((
unsigned char *) &_z,
sizeof(_z));
2218 coord[0] = double(_x);
2219 coord[1] = double(_y);
2220 coord[2] = double(_z);
2222 printf(
"Error: Only float or double formats are supported!\n");
2226 }
else if(!strcmp(mode,
"ASCII")) {
2227 for(i = 0; i < nverts; i++){
2228 bufferp = readline(line, fp, &line_count);
2229 if (bufferp == NULL) {
2230 printf(
"Unexpected end of file on line %d in file %s\n",
2231 line_count, infilename);
2236 coord = &pointlist[i * 3];
2237 for (j = 0; j < 3; j++) {
2238 if (*bufferp ==
'\0') {
2239 printf(
"Syntax error reading vertex coords on line");
2240 printf(
" %d in file %s\n", line_count, infilename);
2244 coord[j] = (REAL) strtod(bufferp, &bufferp);
2245 bufferp = findnextnumber(bufferp);
2252 if(!strcmp(
id,
"POLYGONS")) {
2253 sscanf(line,
"%s %d %d",
id, &nfaces, &dummy);
2255 numberoffacets = nfaces;
2259 if(!strcmp(mode,
"BINARY")) {
2260 for(i = 0; i < nfaces; i++){
2261 fread((
char*)(&nn),
sizeof(
int), 1, fp);
2262 if(ImALittleEndian){
2263 swapBytes((
unsigned char *) &nn,
sizeof(nn));
2268 printf(
"Error: No mixed cells are allowed.\n");
2273 fread((
char*)(&id1),
sizeof(
int), 1, fp);
2274 fread((
char*)(&id2),
sizeof(
int), 1, fp);
2275 fread((
char*)(&id3),
sizeof(
int), 1, fp);
2276 if(ImALittleEndian){
2277 swapBytes((
unsigned char *) &id1,
sizeof(id1));
2278 swapBytes((
unsigned char *) &id2,
sizeof(id2));
2279 swapBytes((
unsigned char *) &id3,
sizeof(id3));
2284 f->numberofpolygons = 1;
2286 p = &f->polygonlist[0];
2289 p->numberofvertices = 3;
2291 p->vertexlist =
new int[p->numberofvertices];
2292 p->vertexlist[0] = id1;
2293 p->vertexlist[1] = id2;
2294 p->vertexlist[2] = id3;
2296 for (j = 0; j < 3; j++) {
2297 if (p->vertexlist[j] < smallestidx) {
2298 smallestidx = p->vertexlist[j];
2302 printf(
"Error: Only triangles are supported\n");
2306 }
else if(!strcmp(mode,
"ASCII")) {
2307 for(i = 0; i < nfaces; i++) {
2308 bufferp = readline(line, fp, &line_count);
2309 nn = (int) strtol(bufferp, &bufferp, 0);
2313 printf(
"Error: No mixed cells are allowed.\n");
2318 bufferp = findnextnumber(bufferp);
2319 id1 = (int) strtol(bufferp, &bufferp, 0);
2320 bufferp = findnextnumber(bufferp);
2321 id2 = (int) strtol(bufferp, &bufferp, 0);
2322 bufferp = findnextnumber(bufferp);
2323 id3 = (int) strtol(bufferp, &bufferp, 0);
2327 f->numberofpolygons = 1;
2329 p = &f->polygonlist[0];
2332 p->numberofvertices = 3;
2334 p->vertexlist =
new int[p->numberofvertices];
2335 p->vertexlist[0] = id1;
2336 p->vertexlist[1] = id2;
2337 p->vertexlist[2] = id3;
2339 for (j = 0; j < 3; j++) {
2340 if (p->vertexlist[j] < smallestidx) {
2341 smallestidx = p->vertexlist[j];
2345 printf(
"Error: Only triangles are supported.\n");
2354 if (smallestidx == 0) {
2356 }
else if (smallestidx == 1) {
2359 printf(
"A wrong smallest index (%d) was detected in file %s\n",
2360 smallestidx, infilename);
2367 if(!strcmp(
id,
"LINES") || !strcmp(
id,
"CELLS")){
2368 printf(
"Warning: load_vtk(): cannot read formats LINES, CELLS.\n");
2381 bool tetgenio::load_plc(
char* filebasename,
int object)
2385 if (
object == (
int) tetgenbehavior::NODES) {
2386 success = load_node(filebasename);
2387 }
else if (
object == (
int) tetgenbehavior::POLY) {
2388 success = load_poly(filebasename);
2389 }
else if (
object == (
int) tetgenbehavior::OFF) {
2390 success = load_off(filebasename);
2391 }
else if (
object == (
int) tetgenbehavior::PLY) {
2392 success = load_ply(filebasename);
2393 }
else if (
object == (
int) tetgenbehavior::STL) {
2394 success = load_stl(filebasename);
2395 }
else if (
object == (
int) tetgenbehavior::MEDIT) {
2396 success = load_medit(filebasename, 0);
2397 }
else if (
object == (
int) tetgenbehavior::VTK) {
2398 success = load_vtk(filebasename);
2400 success = load_poly(filebasename);
2405 load_edge(filebasename);
2406 load_var(filebasename);
2407 load_mtr(filebasename);
2419 bool tetgenio::load_tetmesh(
char* filebasename,
int object)
2423 if (
object == (
int) tetgenbehavior::MEDIT) {
2424 success = load_medit(filebasename, 1);
2425 }
else if (
object == (
int) tetgenbehavior::NEU_MESH) {
2428 success = load_node(filebasename);
2430 success = load_tet(filebasename);
2434 load_face(filebasename);
2435 load_edge(filebasename);
2436 load_vol(filebasename);
2442 load_var(filebasename);
2443 load_mtr(filebasename);
2455 void tetgenio::save_nodes(
char* filebasename)
2458 char outnodefilename[FILENAMESIZE];
2459 char outmtrfilename[FILENAMESIZE];
2462 sprintf(outnodefilename,
"%s.node", filebasename);
2463 printf(
"Saving nodes to %s\n", outnodefilename);
2464 fout = fopen(outnodefilename,
"w");
2465 fprintf(fout,
"%d %d %d %d\n", numberofpoints, mesh_dim,
2466 numberofpointattributes, pointmarkerlist != NULL ? 1 : 0);
2467 for (i = 0; i < numberofpoints; i++) {
2468 if (mesh_dim == 2) {
2469 fprintf(fout,
"%d %.16g %.16g", i + firstnumber, pointlist[i * 3],
2470 pointlist[i * 3 + 1]);
2472 fprintf(fout,
"%d %.16g %.16g %.16g", i + firstnumber,
2473 pointlist[i * 3], pointlist[i * 3 + 1], pointlist[i * 3 + 2]);
2475 for (j = 0; j < numberofpointattributes; j++) {
2476 fprintf(fout,
" %.16g",
2477 pointattributelist[i * numberofpointattributes + j]);
2479 if (pointmarkerlist != NULL) {
2480 fprintf(fout,
" %d", pointmarkerlist[i]);
2482 fprintf(fout,
"\n");
2487 if ((numberofpointmtrs > 0) && (pointmtrlist != (REAL *) NULL)) {
2488 sprintf(outmtrfilename,
"%s.mtr", filebasename);
2489 printf(
"Saving metrics to %s\n", outmtrfilename);
2490 fout = fopen(outmtrfilename,
"w");
2491 fprintf(fout,
"%d %d\n", numberofpoints, numberofpointmtrs);
2492 for (i = 0; i < numberofpoints; i++) {
2493 for (j = 0; j < numberofpointmtrs; j++) {
2494 fprintf(fout,
"%.16g ", pointmtrlist[i * numberofpointmtrs + j]);
2496 fprintf(fout,
"\n");
2508 void tetgenio::save_elements(
char* filebasename)
2511 char outelefilename[FILENAMESIZE];
2514 sprintf(outelefilename,
"%s.ele", filebasename);
2515 printf(
"Saving elements to %s\n", outelefilename);
2516 fout = fopen(outelefilename,
"w");
2517 if (mesh_dim == 3) {
2518 fprintf(fout,
"%d %d %d\n", numberoftetrahedra, numberofcorners,
2519 numberoftetrahedronattributes);
2520 for (i = 0; i < numberoftetrahedra; i++) {
2521 fprintf(fout,
"%d", i + firstnumber);
2522 for (j = 0; j < numberofcorners; j++) {
2523 fprintf(fout,
" %5d", tetrahedronlist[i * numberofcorners + j]);
2525 for (j = 0; j < numberoftetrahedronattributes; j++) {
2526 fprintf(fout,
" %g",
2527 tetrahedronattributelist[i * numberoftetrahedronattributes + j]);
2529 fprintf(fout,
"\n");
2533 fprintf(fout,
"%d %d %d\n",numberoftrifaces,3,trifacemarkerlist ? 1 : 0);
2534 for (i = 0; i < numberoftrifaces; i++) {
2535 fprintf(fout,
"%d", i + firstnumber);
2536 for (j = 0; j < 3; j++) {
2537 fprintf(fout,
" %5d", trifacelist[i * 3 + j]);
2539 if (trifacemarkerlist != NULL) {
2540 fprintf(fout,
" %d", trifacemarkerlist[i]);
2542 fprintf(fout,
"\n");
2555 void tetgenio::save_faces(
char* filebasename)
2558 char outfacefilename[FILENAMESIZE];
2561 sprintf(outfacefilename,
"%s.face", filebasename);
2562 printf(
"Saving faces to %s\n", outfacefilename);
2563 fout = fopen(outfacefilename,
"w");
2564 fprintf(fout,
"%d %d\n", numberoftrifaces,
2565 trifacemarkerlist != NULL ? 1 : 0);
2566 for (i = 0; i < numberoftrifaces; i++) {
2567 fprintf(fout,
"%d %5d %5d %5d", i + firstnumber, trifacelist[i * 3],
2568 trifacelist[i * 3 + 1], trifacelist[i * 3 + 2]);
2569 if (trifacemarkerlist != NULL) {
2570 fprintf(fout,
" %d", trifacemarkerlist[i]);
2572 fprintf(fout,
"\n");
2584 void tetgenio::save_edges(
char* filebasename)
2587 char outedgefilename[FILENAMESIZE];
2590 sprintf(outedgefilename,
"%s.edge", filebasename);
2591 printf(
"Saving edges to %s\n", outedgefilename);
2592 fout = fopen(outedgefilename,
"w");
2593 fprintf(fout,
"%d %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
2594 for (i = 0; i < numberofedges; i++) {
2595 fprintf(fout,
"%d %4d %4d", i + firstnumber, edgelist[i * 2],
2596 edgelist[i * 2 + 1]);
2597 if (edgemarkerlist != NULL) {
2598 fprintf(fout,
" %d", edgemarkerlist[i]);
2600 fprintf(fout,
"\n");
2612 void tetgenio::save_neighbors(
char* filebasename)
2615 char outneighborfilename[FILENAMESIZE];
2618 sprintf(outneighborfilename,
"%s.neigh", filebasename);
2619 printf(
"Saving neighbors to %s\n", outneighborfilename);
2620 fout = fopen(outneighborfilename,
"w");
2621 fprintf(fout,
"%d %d\n", numberoftetrahedra, mesh_dim + 1);
2622 for (i = 0; i < numberoftetrahedra; i++) {
2623 if (mesh_dim == 2) {
2624 fprintf(fout,
"%d %5d %5d %5d", i + firstnumber, neighborlist[i * 3],
2625 neighborlist[i * 3 + 1], neighborlist[i * 3 + 2]);
2627 fprintf(fout,
"%d %5d %5d %5d %5d", i + firstnumber,
2628 neighborlist[i * 4], neighborlist[i * 4 + 1],
2629 neighborlist[i * 4 + 2], neighborlist[i * 4 + 3]);
2631 fprintf(fout,
"\n");
2645 void tetgenio::save_poly(
char* filebasename)
2650 char outpolyfilename[FILENAMESIZE];
2653 sprintf(outpolyfilename,
"%s.poly", filebasename);
2654 printf(
"Saving poly to %s\n", outpolyfilename);
2655 fout = fopen(outpolyfilename,
"w");
2660 fprintf(fout,
"%d %d %d %d\n", 0, mesh_dim, numberofpointattributes,
2661 pointmarkerlist != NULL ? 1 : 0);
2664 if (mesh_dim == 2) {
2666 fprintf(fout,
"%d %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
2667 for (i = 0; i < numberofedges; i++) {
2668 fprintf(fout,
"%d %4d %4d", i + firstnumber, edgelist[i * 2],
2669 edgelist[i * 2 + 1]);
2670 if (edgemarkerlist != NULL) {
2671 fprintf(fout,
" %d", edgemarkerlist[i]);
2673 fprintf(fout,
"\n");
2677 fprintf(fout,
"%d %d\n", numberoffacets, facetmarkerlist != NULL ? 1 : 0);
2678 for (i = 0; i < numberoffacets; i++) {
2679 f = &(facetlist[i]);
2680 fprintf(fout,
"%d %d %d # %d\n", f->numberofpolygons,f->numberofholes,
2681 facetmarkerlist != NULL ? facetmarkerlist[i] : 0, i + firstnumber);
2683 for (j = 0; j < f->numberofpolygons; j++) {
2684 p = &(f->polygonlist[j]);
2685 fprintf(fout,
"%d ", p->numberofvertices);
2686 for (k = 0; k < p->numberofvertices; k++) {
2687 if (((k + 1) % 10) == 0) {
2688 fprintf(fout,
"\n ");
2690 fprintf(fout,
" %d", p->vertexlist[k]);
2692 fprintf(fout,
"\n");
2695 for (j = 0; j < f->numberofholes; j++) {
2696 fprintf(fout,
"%d %.12g %.12g %.12g\n", j + firstnumber,
2697 f->holelist[j * 3], f->holelist[j * 3 + 1], f->holelist[j * 3 + 2]);
2703 fprintf(fout,
"%d\n", numberofholes);
2704 for (i = 0; i < numberofholes; i++) {
2706 fprintf(fout,
"%d %.12g %.12g", i + firstnumber, holelist[i * mesh_dim],
2707 holelist[i * mesh_dim + 1]);
2708 if (mesh_dim == 3) {
2710 fprintf(fout,
" %.12g", holelist[i * mesh_dim + 2]);
2712 fprintf(fout,
"\n");
2716 fprintf(fout,
"%d\n", numberofregions);
2717 for (i = 0; i < numberofregions; i++) {
2718 if (mesh_dim == 2) {
2721 fprintf(fout,
"%d %.12g %.12g %.12g %.12g\n", i + firstnumber,
2722 regionlist[i * 4], regionlist[i * 4 + 1],
2723 regionlist[i * 4 + 2], regionlist[i * 4 + 3]);
2727 fprintf(fout,
"%d %.12g %.12g %.12g %.12g %.12g\n", i + firstnumber,
2728 regionlist[i * 5], regionlist[i * 5 + 1],
2729 regionlist[i * 5 + 2], regionlist[i * 5 + 3],
2730 regionlist[i * 5 + 4]);
2745 void tetgenio::save_faces2smesh(
char* filebasename)
2748 char outsmeshfilename[FILENAMESIZE];
2751 sprintf(outsmeshfilename,
"%s.smesh", filebasename);
2752 printf(
"Saving faces to %s\n", outsmeshfilename);
2753 fout = fopen(outsmeshfilename,
"w");
2758 fprintf(fout,
"%d %d %d %d\n", 0, mesh_dim, numberofpointattributes,
2759 pointmarkerlist != NULL ? 1 : 0);
2762 fprintf(fout,
"%d %d\n", numberoftrifaces,
2763 trifacemarkerlist != NULL ? 1 : 0);
2766 for (i = 0; i < numberoftrifaces; i++) {
2768 fprintf(fout,
"3 %d %d %d", trifacelist[j], trifacelist[j + 1],
2769 trifacelist[j + 2]);
2770 if (trifacemarkerlist != NULL) {
2771 fprintf(fout,
" %d", trifacemarkerlist[i]);
2773 fprintf(fout,
"\n");
2777 fprintf(fout,
"0\n");
2778 fprintf(fout,
"0\n");
2795 char* tetgenio::readline(
char *
string, FILE *infile,
int *linenumber)
2801 result = fgets(
string, INPUTLINESIZE - 1, infile);
2802 if (linenumber) (*linenumber)++;
2803 if (result == (
char *) NULL) {
2804 return (
char *) NULL;
2807 while ((*result ==
' ') || (*result ==
'\t')) result++;
2809 }
while ((*result ==
'\0') || (*result ==
'\r') || (*result ==
'\n'));
2822 char* tetgenio::findnextfield(
char *
string)
2828 while ((*result !=
'\0') && (*result !=
' ') && (*result !=
'\t') &&
2829 (*result !=
',') && (*result !=
';')) {
2834 while ((*result ==
' ') || (*result ==
'\t') || (*result ==
',') ||
2850 char* tetgenio::readnumberline(
char *
string, FILE *infile,
char *infilename)
2856 result = fgets(
string, INPUTLINESIZE, infile);
2857 if (result == (
char *) NULL) {
2862 while ((*result !=
'\0') && (*result !=
'#')
2863 && (*result !=
'.') && (*result !=
'+') && (*result !=
'-')
2864 && ((*result <
'0') || (*result >
'9'))) {
2868 }
while ((*result ==
'#') || (*result ==
'\0'));
2882 char* tetgenio::findnextnumber(
char *
string)
2888 while ((*result !=
'\0') && (*result !=
'#') && (*result !=
' ') &&
2889 (*result !=
'\t') && (*result !=
',')) {
2894 while ((*result !=
'\0') && (*result !=
'#')
2895 && (*result !=
'.') && (*result !=
'+') && (*result !=
'-')
2896 && ((*result <
'0') || (*result >
'9'))) {
2900 if (*result ==
'#') {
2921 void tetgenbehavior::syntax()
2923 printf(
" tetgen [-pYrq_Aa_miO_S_T_XMwcdzfenvgkJBNEFICQVh] input_file\n");
2924 printf(
" -p Tetrahedralizes a piecewise linear complex (PLC).\n");
2925 printf(
" -Y Preserves the input surface mesh (does not modify it).\n");
2926 printf(
" -r Reconstructs a previously generated mesh.\n");
2927 printf(
" -q Refines mesh (to improve mesh quality).\n");
2928 printf(
" -R Mesh coarsening (to reduce the mesh elements).\n");
2929 printf(
" -A Assigns attributes to tetrahedra in different regions.\n");
2930 printf(
" -a Applies a maximum tetrahedron volume constraint.\n");
2931 printf(
" -m Applies a mesh sizing function.\n");
2932 printf(
" -i Inserts a list of additional points.\n");
2933 printf(
" -O Specifies the level of mesh optimization.\n");
2934 printf(
" -S Specifies maximum number of added points.\n");
2935 printf(
" -T Sets a tolerance for coplanar test (default 1e-8).\n");
2936 printf(
" -X Suppresses use of exact arithmetic.\n");
2937 printf(
" -M No merge of coplanar facets or very close vertices.\n");
2938 printf(
" -w Generates weighted Delaunay (regular) triangulation.\n");
2939 printf(
" -c Retains the convex hull of the PLC.\n");
2940 printf(
" -d Detects self-intersections of facets of the PLC.\n");
2941 printf(
" -z Numbers all output items starting from zero.\n");
2942 printf(
" -f Outputs all faces to .face file.\n");
2943 printf(
" -e Outputs all edges to .edge file.\n");
2944 printf(
" -n Outputs tetrahedra neighbors to .neigh file.\n");
2945 printf(
" -v Outputs Voronoi diagram to files.\n");
2946 printf(
" -g Outputs mesh to .mesh file for viewing by Medit.\n");
2947 printf(
" -k Outputs mesh to .vtk file for viewing by Paraview.\n");
2948 printf(
" -J No jettison of unused vertices from output .node file.\n");
2949 printf(
" -B Suppresses output of boundary information.\n");
2950 printf(
" -N Suppresses output of .node file.\n");
2951 printf(
" -E Suppresses output of .ele file.\n");
2952 printf(
" -F Suppresses output of .face and .edge file.\n");
2953 printf(
" -I Suppresses mesh iteration numbers.\n");
2954 printf(
" -C Checks the consistency of the final mesh.\n");
2955 printf(
" -Q Quiet: No terminal output except errors.\n");
2956 printf(
" -V Verbose: Detailed information, more terminal output.\n");
2957 printf(
" -h Help: A brief instruction for using TetGen.\n");
2966 void tetgenbehavior::usage()
2969 printf(
"A Quality Tetrahedral Mesh Generator and 3D Delaunay ");
2970 printf(
"Triangulator\n");
2971 printf(
"Version 1.5\n");
2972 printf(
"August 18, 2018\n");
2974 printf(
"Copyright (C) 2002 - 2018\n");
2976 printf(
"What Can TetGen Do?\n");
2978 printf(
" TetGen generates Delaunay tetrahedralizations, constrained\n");
2979 printf(
" Delaunay tetrahedralizations, and quality tetrahedral meshes.\n");
2981 printf(
"Command Line Syntax:\n");
2983 printf(
" Below is the basic command line syntax of TetGen with a list of ");
2985 printf(
" descriptions. Underscores indicate that numbers may optionally\n");
2986 printf(
" follow certain switches. Do not leave any space between a ");
2988 printf(
" and its numeric parameter. \'input_file\' contains input data\n");
2989 printf(
" depending on the switches you supplied which may be a ");
2990 printf(
" piecewise\n");
2991 printf(
" linear complex or a list of nodes. File formats and detailed\n");
2992 printf(
" description of command line switches are found in user's ");
2993 printf(
"manual.\n");
2997 printf(
"Examples of How to Use TetGen:\n");
2999 printf(
" \'tetgen object\' reads vertices from object.node, and writes ");
3000 printf(
"their\n Delaunay tetrahedralization to object.1.node, ");
3001 printf(
"object.1.ele\n (tetrahedra), and object.1.face");
3002 printf(
" (convex hull faces).\n");
3004 printf(
" \'tetgen -p object\' reads a PLC from object.poly or object.");
3005 printf(
"smesh (and\n possibly object.node) and writes its constrained ");
3006 printf(
"Delaunay\n tetrahedralization to object.1.node, object.1.ele, ");
3007 printf(
"object.1.face,\n");
3008 printf(
" (boundary faces) and object.1.edge (boundary edges).\n");
3010 printf(
" \'tetgen -pq1.414a.1 object\' reads a PLC from object.poly or\n");
3011 printf(
" object.smesh (and possibly object.node), generates a mesh ");
3012 printf(
"whose\n tetrahedra have radius-edge ratio smaller than 1.414 and ");
3013 printf(
"have volume\n of 0.1 or less, and writes the mesh to ");
3014 printf(
"object.1.node, object.1.ele,\n object.1.face, and object.1.edge\n");
3016 printf(
"Please send bugs/comments to Hang Si <si@wias-berlin.de>\n");
3017 terminatetetgen(NULL, 0);
3031 bool tetgenbehavior::parse_commandline(
int argc,
char **argv)
3037 char workstring[1024];
3043 commandline[0] =
'\0';
3046 strcpy(commandline, argv[0]);
3047 strcat(commandline,
" ");
3050 for (i = startindex; i < argc; i++) {
3052 strcat(commandline, argv[i]);
3053 strcat(commandline,
" ");
3054 if (startindex == 1) {
3056 if (argv[i][0] !=
'-') {
3057 strncpy(infilename, argv[i], 1024 - 1);
3058 infilename[1024 - 1] =
'\0';
3063 for (j = startindex; argv[i][j] !=
'\0'; j++) {
3064 if (argv[i][j] ==
'p') {
3066 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3067 (argv[i][j + 1] ==
'.')) {
3069 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3070 (argv[i][j + 1] ==
'.')) {
3072 workstring[k] = argv[i][j];
3075 workstring[k] =
'\0';
3076 facet_separate_ang_tol = (REAL) strtod(workstring, (
char **) NULL);
3078 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3080 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3081 (argv[i][j + 1] ==
'.')) {
3083 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3084 (argv[i][j + 1] ==
'.') || (argv[i][j + 1] ==
'e') ||
3085 (argv[i][j + 1] ==
'-') || (argv[i][j + 1] ==
'+')) {
3087 workstring[k] = argv[i][j];
3090 workstring[k] =
'\0';
3091 facet_overlap_ang_tol = (REAL) strtod(workstring, (
char **) NULL);
3094 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3096 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3097 (argv[i][j + 1] ==
'.')) {
3099 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3100 (argv[i][j + 1] ==
'.')) {
3102 workstring[k] = argv[i][j];
3105 workstring[k] =
'\0';
3106 facet_small_ang_tol = (REAL) strtod(workstring, (
char **) NULL);
3109 }
else if (argv[i][j] ==
's') {
3111 }
else if (argv[i][j] ==
'Y') {
3113 if ((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) {
3114 nobisect_nomerge = (argv[i][j + 1] -
'0');
3117 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3119 if ((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) {
3120 supsteiner_level = (argv[i][j + 1] -
'0');
3124 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3126 if ((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) {
3127 addsteiner_algo = (argv[i][j + 1] -
'0');
3131 }
else if (argv[i][j] ==
'r') {
3133 }
else if (argv[i][j] ==
'q') {
3135 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3136 (argv[i][j + 1] ==
'.')) {
3138 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3139 (argv[i][j + 1] ==
'.')) {
3141 workstring[k] = argv[i][j];
3144 workstring[k] =
'\0';
3145 minratio = (REAL) strtod(workstring, (
char **) NULL);
3147 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3149 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3150 (argv[i][j + 1] ==
'.')) {
3152 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3153 (argv[i][j + 1] ==
'.')) {
3155 workstring[k] = argv[i][j];
3158 workstring[k] =
'\0';
3159 mindihedral = (REAL) strtod(workstring, (
char **) NULL);
3162 }
else if (argv[i][j] ==
'R') {
3164 if ((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) {
3165 coarsen_param = (argv[i][j + 1] -
'0');
3168 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3170 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3171 (argv[i][j + 1] ==
'.')) {
3173 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3174 (argv[i][j + 1] ==
'.')) {
3176 workstring[k] = argv[i][j];
3179 workstring[k] =
'\0';
3180 coarsen_percent = (REAL) strtod(workstring, (
char **) NULL);
3183 }
else if (argv[i][j] ==
'w') {
3185 if ((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) {
3186 weighted_param = (argv[i][j + 1] -
'0');
3189 }
else if (argv[i][j] ==
'b') {
3192 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3193 (argv[i][j + 1] ==
'.')) {
3195 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3196 (argv[i][j + 1] ==
'.')) {
3198 workstring[k] = argv[i][j];
3201 workstring[k] =
'\0';
3202 brio_threshold = (int) strtol(workstring, (
char **) &workstring, 0);
3204 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3206 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3207 (argv[i][j + 1] ==
'.')) {
3209 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3210 (argv[i][j + 1] ==
'.')) {
3212 workstring[k] = argv[i][j];
3215 workstring[k] =
'\0';
3216 brio_ratio = (REAL) strtod(workstring, (
char **) NULL);
3219 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3221 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3222 (argv[i][j + 1] ==
'.') || (argv[i][j + 1] ==
'-')) {
3224 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3225 (argv[i][j + 1] ==
'.') || (argv[i][j + 1] ==
'-')) {
3227 workstring[k] = argv[i][j];
3230 workstring[k] =
'\0';
3231 hilbert_limit = (int) strtol(workstring, (
char **) &workstring, 0);
3234 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3236 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3237 (argv[i][j + 1] ==
'.') || (argv[i][j + 1] ==
'-')) {
3239 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3240 (argv[i][j + 1] ==
'.') || (argv[i][j + 1] ==
'-')) {
3242 workstring[k] = argv[i][j];
3245 workstring[k] =
'\0';
3246 hilbert_order = (REAL) strtod(workstring, (
char **) NULL);
3249 if (brio_threshold == 0) {
3252 if (brio_ratio >= 1.0) {
3256 }
else if (argv[i][j] ==
'l') {
3258 }
else if (argv[i][j] ==
'L') {
3260 }
else if (argv[i][j] ==
'm') {
3262 }
else if (argv[i][j] ==
'a') {
3263 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3264 (argv[i][j + 1] ==
'.')) {
3267 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3268 (argv[i][j + 1] ==
'.') || (argv[i][j + 1] ==
'e') ||
3269 (argv[i][j + 1] ==
'-') || (argv[i][j + 1] ==
'+')) {
3271 workstring[k] = argv[i][j];
3274 workstring[k] =
'\0';
3275 maxvolume = (REAL) strtod(workstring, (
char **) NULL);
3279 }
else if (argv[i][j] ==
'A') {
3281 }
else if (argv[i][j] ==
'D') {
3283 if (argv[i][j + 1] ==
'l') {
3284 use_equatorial_lens = 1;
3285 }
else if ((argv[i][j + 1] >=
'1') && (argv[i][j + 1] <=
'3')) {
3286 reflevel = (argv[i][j + 1] -
'1') + 1;
3289 }
else if (argv[i][j] ==
'i') {
3290 insertaddpoints = 1;
3291 }
else if (argv[i][j] ==
'd') {
3293 }
else if (argv[i][j] ==
'c') {
3295 }
else if (argv[i][j] ==
'M') {
3298 if ((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'1')) {
3299 nomergefacet = (argv[i][j + 1] -
'0');
3302 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3304 if ((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'1')) {
3305 nomergevertex = (argv[i][j + 1] -
'0');
3309 }
else if (argv[i][j] ==
'X') {
3310 if (argv[i][j + 1] ==
'1') {
3316 }
else if (argv[i][j] ==
'z') {
3317 if (argv[i][j + 1] ==
'1') {
3323 }
else if (argv[i][j] ==
'f') {
3325 }
else if (argv[i][j] ==
'e') {
3327 }
else if (argv[i][j] ==
'n') {
3329 }
else if (argv[i][j] ==
'v') {
3331 }
else if (argv[i][j] ==
'g') {
3333 }
else if (argv[i][j] ==
'k') {
3335 }
else if (argv[i][j] ==
'J') {
3337 }
else if (argv[i][j] ==
'B') {
3339 }
else if (argv[i][j] ==
'N') {
3341 }
else if (argv[i][j] ==
'E') {
3343 }
else if (argv[i][j] ==
'F') {
3345 }
else if (argv[i][j] ==
'I') {
3347 }
else if (argv[i][j] ==
'S') {
3348 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3349 (argv[i][j + 1] ==
'.')) {
3351 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3352 (argv[i][j + 1] ==
'.') || (argv[i][j + 1] ==
'e') ||
3353 (argv[i][j + 1] ==
'-') || (argv[i][j + 1] ==
'+')) {
3355 workstring[k] = argv[i][j];
3358 workstring[k] =
'\0';
3359 steinerleft = (int) strtol(workstring, (
char **) NULL, 0);
3361 }
else if (argv[i][j] ==
'o') {
3362 if (argv[i][j + 1] ==
'2') {
3366 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3368 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3369 (argv[i][j + 1] ==
'.')) {
3371 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3372 (argv[i][j + 1] ==
'.')) {
3374 workstring[k] = argv[i][j];
3377 workstring[k] =
'\0';
3378 optmaxdihedral = (REAL) strtod(workstring, (
char **) NULL);
3381 }
else if (argv[i][j] ==
'O') {
3382 if ((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) {
3383 optlevel = (argv[i][j + 1] -
'0');
3386 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3388 if ((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'7')) {
3389 optscheme = (argv[i][j + 1] -
'0');
3393 }
else if (argv[i][j] ==
'T') {
3394 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3395 (argv[i][j + 1] ==
'.')) {
3397 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3398 (argv[i][j + 1] ==
'.') || (argv[i][j + 1] ==
'e') ||
3399 (argv[i][j + 1] ==
'-') || (argv[i][j + 1] ==
'+')) {
3401 workstring[k] = argv[i][j];
3404 workstring[k] =
'\0';
3405 epsilon = (REAL) strtod(workstring, (
char **) NULL);
3407 }
else if (argv[i][j] ==
'C') {
3409 }
else if (argv[i][j] ==
'Q') {
3411 }
else if (argv[i][j] ==
'V') {
3413 }
else if (argv[i][j] ==
'x') {
3414 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3415 (argv[i][j + 1] ==
'.')) {
3417 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3418 (argv[i][j + 1] ==
'.') || (argv[i][j + 1] ==
'e') ||
3419 (argv[i][j + 1] ==
'-') || (argv[i][j + 1] ==
'+')) {
3421 workstring[k] = argv[i][j];
3424 workstring[k] =
'\0';
3425 tetrahedraperblock = (int) strtol(workstring, (
char **) NULL, 0);
3426 if (tetrahedraperblock > 8188) {
3427 vertexperblock = tetrahedraperblock / 2;
3428 shellfaceperblock = vertexperblock / 2;
3430 tetrahedraperblock = 8188;
3433 }
else if (argv[i][j] ==
'H') {
3434 if (argv[i+1][0] !=
'-') {
3437 strncpy(hole_mesh_filename, argv[i+1], 1024 - 1);
3438 hole_mesh_filename[1024 - 1] =
'\0';
3442 }
else if (argv[i][j] ==
'K') {
3444 }
else if ((argv[i][j] ==
'h') ||
3445 (argv[i][j] ==
'?')) {
3448 printf(
"Warning: Unknown switch -%c.\n", argv[i][j]);
3453 if (startindex == 0) {
3455 strcpy(infilename,
"tetgen-tmpfile");
3457 if (infilename[0] ==
'\0') {
3460 terminatetetgen(NULL, 0);
3463 if (!strcmp(&infilename[strlen(infilename) - 5],
".node")) {
3464 infilename[strlen(infilename) - 5] =
'\0';
3466 }
else if (!strcmp(&infilename[strlen(infilename) - 5],
".poly")) {
3467 infilename[strlen(infilename) - 5] =
'\0';
3470 }
else if (!strcmp(&infilename[strlen(infilename) - 6],
".smesh")) {
3471 infilename[strlen(infilename) - 6] =
'\0';
3474 }
else if (!strcmp(&infilename[strlen(infilename) - 4],
".off")) {
3475 infilename[strlen(infilename) - 4] =
'\0';
3478 }
else if (!strcmp(&infilename[strlen(infilename) - 4],
".ply")) {
3479 infilename[strlen(infilename) - 4] =
'\0';
3482 }
else if (!strcmp(&infilename[strlen(infilename) - 4],
".stl")) {
3483 infilename[strlen(infilename) - 4] =
'\0';
3486 }
else if (!strcmp(&infilename[strlen(infilename) - 5],
".mesh")) {
3487 infilename[strlen(infilename) - 5] =
'\0';
3489 if (!refine) plc = 1;
3490 }
else if (!strcmp(&infilename[strlen(infilename) - 4],
".vtk")) {
3491 infilename[strlen(infilename) - 4] =
'\0';
3494 }
else if (!strcmp(&infilename[strlen(infilename) - 4],
".ele")) {
3495 infilename[strlen(infilename) - 4] =
'\0';
3498 }
else if (!strcmp(&infilename[strlen(infilename) - 4],
".neu")) {
3499 infilename[strlen(infilename) - 4] =
'\0';
3505 if (nobisect && (!plc && !refine)) {
3508 if (quality && (!plc && !refine)) {
3511 if (diagnose && !plc) {
3514 if (refine && !quality) {
3518 if (insertaddpoints && (optlevel == 0)) {
3521 if (coarsen && (optlevel == 0)) {
3526 if ((refine || plc) && weighted) {
3527 printf(
"Error: Switches -w cannot use together with -p or -r.\n");
3532 if (plc && !regionattrib) {
3541 if (refine || !plc) {
3546 if (!refine && !plc) {
3550 if (fixedvolume || varvolume) {
3553 if (!plc && !refine) {
3560 if (optmaxdihedral < 179.0) {
3562 optmaxdihedral = 179.0;
3564 optmaxdihedral = 179.999;
3567 if (optminsmtdihed < 179.999) {
3568 optminsmtdihed = 179.999;
3570 if (optminslidihed < 179.999) {
3571 optminslidihed = 179.999;
3576 strcpy(workstring, infilename);
3578 while (workstring[j] !=
'\0') {
3579 if ((workstring[j] ==
'.') && (workstring[j + 1] !=
'\0')) {
3585 if (increment > 0) {
3588 if ((workstring[j] >=
'0') && (workstring[j] <=
'9')) {
3589 meshnumber = meshnumber * 10 + (int) (workstring[j] -
'0');
3594 }
while (workstring[j] !=
'\0');
3596 if (noiterationnum) {
3597 strcpy(outfilename, infilename);
3598 }
else if (increment == 0) {
3599 strcpy(outfilename, infilename);
3600 strcat(outfilename,
".1");
3602 workstring[increment] =
'%';
3603 workstring[increment + 1] =
'd';
3604 workstring[increment + 2] =
'\0';
3605 sprintf(outfilename, workstring, meshnumber + 1);
3608 strcpy(addinfilename, infilename);
3609 strcat(addinfilename,
".a");
3611 strcpy(bgmeshfilename, infilename);
3612 strcat(bgmeshfilename,
".b");
3627 int tetgenmesh::bondtbl[12][12] = {{0,},};
3628 int tetgenmesh::enexttbl[12] = {0,};
3629 int tetgenmesh::eprevtbl[12] = {0,};
3630 int tetgenmesh::enextesymtbl[12] = {0,};
3631 int tetgenmesh::eprevesymtbl[12] = {0,};
3632 int tetgenmesh::eorgoppotbl[12] = {0,};
3633 int tetgenmesh::edestoppotbl[12] = {0,};
3634 int tetgenmesh::fsymtbl[12][12] = {{0,},};
3635 int tetgenmesh::facepivot1[12] = {0,};
3636 int tetgenmesh::facepivot2[12][12] = {{0,},};
3637 int tetgenmesh::tsbondtbl[12][6] = {{0,},};
3638 int tetgenmesh::stbondtbl[12][6] = {{0,},};
3639 int tetgenmesh::tspivottbl[12][6] = {{0,},};
3640 int tetgenmesh::stpivottbl[12][6] = {{0,},};
3645 int tetgenmesh::esymtbl[12] = {9, 6, 11, 4, 3, 7, 1, 5, 10, 0, 8, 2};
3651 int tetgenmesh:: orgpivot[12] = {7, 7, 5, 5, 6, 4, 4, 6, 5, 6, 7, 4};
3652 int tetgenmesh::destpivot[12] = {6, 4, 4, 6, 5, 6, 7, 4, 7, 7, 5, 5};
3653 int tetgenmesh::apexpivot[12] = {5, 6, 7, 4, 7, 7, 5, 5, 6, 4, 4, 6};
3654 int tetgenmesh::oppopivot[12] = {4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7};
3659 int tetgenmesh::ver2edge[12] = {0, 1, 2, 3, 3, 5, 1, 5, 4, 0, 4, 2};
3660 int tetgenmesh::edge2ver[ 6] = {0, 1, 2, 3, 8, 5};
3664 int tetgenmesh::epivot[12] = {4, 5, 2, 11, 4, 5, 2, 11, 4, 5, 2, 11};
3670 int tetgenmesh::snextpivot[6] = {2, 5, 4, 1, 0, 3};
3676 int tetgenmesh::sorgpivot [6] = {3, 4, 4, 5, 5, 3};
3677 int tetgenmesh::sdestpivot[6] = {4, 3, 5, 4, 3, 5};
3678 int tetgenmesh::sapexpivot[6] = {5, 5, 3, 3, 4, 4};
3686 void tetgenmesh::inittables()
3688 int soffset, toffset;
3693 for (i = 0; i < 12; i++) {
3694 for (j = 0; j < 12; j++) {
3695 bondtbl[i][j] = (j & 3) + (((i & 12) + (j & 12)) % 12);
3701 for (i = 0; i < 12; i++) {
3702 for (j = 0; j < 12; j++) {
3703 fsymtbl[i][j] = (j + 12 - (i & 12)) % 12;
3708 for (i = 0; i < 12; i++) {
3709 facepivot1[i] = (esymtbl[i] & 3);
3712 for (i = 0; i < 12; i++) {
3713 for (j = 0; j < 12; j++) {
3714 facepivot2[i][j] = fsymtbl[esymtbl[i]][j];
3718 for (i = 0; i < 12; i++) {
3719 enexttbl[i] = (i + 4) % 12;
3720 eprevtbl[i] = (i + 8) % 12;
3723 for (i = 0; i < 12; i++) {
3724 enextesymtbl[i] = esymtbl[enexttbl[i]];
3725 eprevesymtbl[i] = esymtbl[eprevtbl[i]];
3728 for (i = 0; i < 12; i++) {
3729 eorgoppotbl [i] = eprevtbl[esymtbl[enexttbl[i]]];
3730 edestoppotbl[i] = enexttbl[esymtbl[eprevtbl[i]]];
3734 for (i = 0; i < 12; i++) {
3735 for (j = 0; j < 6; j++) {
3737 soffset = (6 - ((i & 12) >> 1)) % 6;
3738 toffset = (12 - ((j & 6) << 1)) % 12;
3740 soffset = (i & 12) >> 1;
3741 toffset = (j & 6) << 1;
3743 tsbondtbl[i][j] = (j & 1) + (((j & 6) + soffset) % 6);
3744 stbondtbl[i][j] = (i & 3) + (((i & 12) + toffset) % 12);
3750 for (i = 0; i < 12; i++) {
3751 for (j = 0; j < 6; j++) {
3753 soffset = (i & 12) >> 1;
3754 toffset = (j & 6) << 1;
3756 soffset = (6 - ((i & 12) >> 1)) % 6;
3757 toffset = (12 - ((j & 6) << 1)) % 12;
3759 tspivottbl[i][j] = (j & 1) + (((j & 6) + soffset) % 6);
3760 stpivottbl[i][j] = (i & 3) + (((i & 12) + toffset) % 12);
3776 void tetgenmesh::arraypool::restart()
3790 void tetgenmesh::arraypool::poolinit(
int sizeofobject,
int log2objperblk)
3793 objectbytes = sizeofobject > 1 ? sizeofobject : 1;
3795 log2objectsperblock = log2objperblk;
3797 objectsperblock = ((int) 1) << log2objectsperblock;
3798 objectsperblockmark = objectsperblock - 1;
3803 toparray = (
char **) NULL;
3816 tetgenmesh::arraypool::arraypool(
int sizeofobject,
int log2objperblk)
3818 poolinit(sizeofobject, log2objperblk);
3821 tetgenmesh::arraypool::~arraypool()
3826 if (toparray != (
char **) NULL) {
3828 for (i = 0; i < toparraylen; i++) {
3830 if (toparray[i] != (
char *) NULL) {
3832 free((
void *) toparray[i]);
3836 free((
void *) toparray);
3840 toparray = (
char **) NULL;
3858 char* tetgenmesh::arraypool::getblock(
int objectindex)
3867 topindex = objectindex >> log2objectsperblock;
3869 if (toparray == (
char **) NULL) {
3872 newsize = topindex + 128;
3873 toparray = (
char **) malloc((
size_t) (newsize *
sizeof(
char *)));
3874 toparraylen = newsize;
3875 for (i = 0; i < newsize; i++) {
3876 toparray[i] = (
char *) NULL;
3879 totalmemory = newsize * (uintptr_t)
sizeof(
char *);
3880 }
else if (topindex >= toparraylen) {
3882 newsize = 3 * toparraylen;
3883 if (topindex >= newsize) {
3884 newsize = topindex + 128;
3888 newarray = (
char **) malloc((
size_t) (newsize *
sizeof(
char *)));
3889 for (i = 0; i < toparraylen; i++) {
3890 newarray[i] = toparray[i];
3892 for (i = toparraylen; i < newsize; i++) {
3893 newarray[i] = (
char *) NULL;
3897 totalmemory += (newsize - toparraylen) *
sizeof(
char *);
3898 toparray = newarray;
3899 toparraylen = newsize;
3903 block = toparray[topindex];
3904 if (block == (
char *) NULL) {
3906 block = (
char *) malloc((
size_t) (objectsperblock * objectbytes));
3907 toparray[topindex] = block;
3909 totalmemory += objectsperblock * objectbytes;
3923 void* tetgenmesh::arraypool::lookup(
int objectindex)
3929 if (toparray == (
char **) NULL) {
3930 return (
void *) NULL;
3934 topindex = objectindex >> log2objectsperblock;
3936 if (topindex >= toparraylen) {
3937 return (
void *) NULL;
3941 block = toparray[topindex];
3942 if (block == (
char *) NULL) {
3943 return (
void *) NULL;
3949 return (
void *)(block + (objectindex & (objectsperblock - 1)) * objectbytes);
3960 int tetgenmesh::arraypool::newindex(
void **newptr)
3963 int newindex = objects;
3964 *newptr = (
void *) (getblock(objects) +
3965 (objects & (objectsperblock - 1)) * objectbytes);
3978 tetgenmesh::memorypool::memorypool()
3980 firstblock = nowblock = (
void **) NULL;
3981 nextitem = (
void *) NULL;
3982 deaditemstack = (
void *) NULL;
3983 pathblock = (
void **) NULL;
3984 pathitem = (
void *) NULL;
3986 itembytes = itemwords = 0;
3988 items = maxitems = 0l;
3989 unallocateditems = 0;
3993 tetgenmesh::memorypool::memorypool(
int bytecount,
int itemcount,
int wsize,
3996 poolinit(bytecount, itemcount, wsize, alignment);
4005 tetgenmesh::memorypool::~memorypool()
4007 while (firstblock != (
void **) NULL) {
4008 nowblock = (
void **) *(firstblock);
4010 firstblock = nowblock;
4030 void tetgenmesh::memorypool::poolinit(
int bytecount,
int itemcount,
int wordsize,
4038 if (alignment > wordsize) {
4039 alignbytes = alignment;
4041 alignbytes = wordsize;
4043 if ((
int)
sizeof(
void *) > alignbytes) {
4044 alignbytes = (int)
sizeof(
void *);
4046 itemwords = ((bytecount + alignbytes - 1) / alignbytes)
4047 * (alignbytes / wordsize);
4048 itembytes = itemwords * wordsize;
4049 itemsperblock = itemcount;
4054 firstblock = (
void **) malloc(itemsperblock * itembytes +
sizeof(
void *)
4056 if (firstblock == (
void **) NULL) {
4057 terminatetetgen(NULL, 1);
4060 *(firstblock) = (
void *) NULL;
4074 void tetgenmesh::memorypool::restart()
4082 nowblock = firstblock;
4084 alignptr = (uintptr_t) (nowblock + 1);
4087 (alignptr + (uintptr_t) alignbytes -
4088 (alignptr % (uintptr_t) alignbytes));
4090 unallocateditems = itemsperblock;
4092 deaditemstack = (
void *) NULL;
4101 void* tetgenmesh::memorypool::alloc()
4109 if (deaditemstack != (
void *) NULL) {
4110 newitem = deaditemstack;
4111 deaditemstack = * (
void **) deaditemstack;
4114 if (unallocateditems == 0) {
4116 if (*nowblock == (
void *) NULL) {
4118 newblock = (
void **) malloc(itemsperblock * itembytes +
sizeof(
void *)
4120 if (newblock == (
void **) NULL) {
4121 terminatetetgen(NULL, 1);
4123 *nowblock = (
void *) newblock;
4125 *newblock = (
void *) NULL;
4128 nowblock = (
void **) *nowblock;
4131 alignptr = (uintptr_t) (nowblock + 1);
4134 (alignptr + (uintptr_t) alignbytes -
4135 (alignptr % (uintptr_t) alignbytes));
4137 unallocateditems = itemsperblock;
4142 nextitem = (
void *) ((uintptr_t) nextitem + itembytes);
4158 void tetgenmesh::memorypool::dealloc(
void *dyingitem)
4161 *((
void **) dyingitem) = deaditemstack;
4162 deaditemstack = dyingitem;
4174 void tetgenmesh::memorypool::traversalinit()
4179 pathblock = firstblock;
4181 alignptr = (uintptr_t) (pathblock + 1);
4184 (alignptr + (uintptr_t) alignbytes -
4185 (alignptr % (uintptr_t) alignbytes));
4187 pathitemsleft = itemsperblock;
4202 void* tetgenmesh::memorypool::traverse()
4208 if (pathitem == nextitem) {
4209 return (
void *) NULL;
4212 if (pathitemsleft == 0) {
4214 pathblock = (
void **) *pathblock;
4216 alignptr = (uintptr_t) (pathblock + 1);
4219 (alignptr + (uintptr_t) alignbytes -
4220 (alignptr % (uintptr_t) alignbytes));
4222 pathitemsleft = itemsperblock;
4226 pathitem = (
void *) ((uintptr_t) pathitem + itembytes);
4241 void tetgenmesh::makeindex2pointmap(point*& idx2verlist)
4246 if (b->verbose > 1) {
4247 printf(
" Constructing mapping from indices to points.\n");
4250 idx2verlist =
new point[points->items + 1];
4252 points->traversalinit();
4253 pointloop = pointtraverse();
4254 idx = in->firstnumber;
4255 while (pointloop != (point) NULL) {
4256 idx2verlist[idx++] = pointloop;
4257 pointloop = pointtraverse();
4275 void tetgenmesh::makepoint2submap(memorypool* pool,
int*& idx2faclist,
4276 face*& facperverlist)
4281 if (b->verbose > 1) {
4282 printf(
" Making a map from points to subfaces.\n");
4286 idx2faclist =
new int[points->items + 1];
4287 for (i = 0; i < points->items + 1; i++) idx2faclist[i] = 0;
4290 pool->traversalinit();
4291 shloop.sh = shellfacetraverse(pool);
4292 while (shloop.sh != (shellface *) NULL) {
4294 j = pointmark((point) shloop.sh[3]) - in->firstnumber;
4296 j = pointmark((point) shloop.sh[4]) - in->firstnumber;
4299 if (shloop.sh[5] != NULL) {
4300 j = pointmark((point) shloop.sh[5]) - in->firstnumber;
4303 shloop.sh = shellfacetraverse(pool);
4309 for (i = 0; i < points->items; i++) {
4310 k = idx2faclist[i + 1];
4311 idx2faclist[i + 1] = idx2faclist[i] + j;
4316 facperverlist =
new face[idx2faclist[i]];
4319 pool->traversalinit();
4320 shloop.sh = shellfacetraverse(pool);
4321 while (shloop.sh != (shellface *) NULL) {
4322 j = pointmark((point) shloop.sh[3]) - in->firstnumber;
4324 facperverlist[idx2faclist[j]] = shloop;
4327 if (shloop.sh[5] != NULL) {
4328 j = pointmark((point) shloop.sh[4]) - in->firstnumber;
4330 facperverlist[idx2faclist[j]] = shloop;
4332 j = pointmark((point) shloop.sh[5]) - in->firstnumber;
4334 facperverlist[idx2faclist[j]] = shloop;
4337 j = pointmark((point) shloop.sh[4]) - in->firstnumber;
4339 facperverlist[idx2faclist[j]] = shloop;
4342 shloop.sh = shellfacetraverse(pool);
4346 for (i = points->items - 1; i >= 0; i--) {
4347 idx2faclist[i + 1] = idx2faclist[i];
4358 void tetgenmesh::tetrahedrondealloc(tetrahedron *dyingtetrahedron)
4362 dyingtetrahedron[4] = (tetrahedron) NULL;
4365 if (dyingtetrahedron[8] != NULL) {
4366 tet2segpool->dealloc((shellface *) dyingtetrahedron[8]);
4368 if (dyingtetrahedron[9] != NULL) {
4369 tet2subpool->dealloc((shellface *) dyingtetrahedron[9]);
4372 tetrahedrons->dealloc((
void *) dyingtetrahedron);
4381 tetgenmesh::tetrahedron* tetgenmesh::tetrahedrontraverse()
4383 tetrahedron *newtetrahedron;
4386 newtetrahedron = (tetrahedron *) tetrahedrons->traverse();
4387 if (newtetrahedron == (tetrahedron *) NULL) {
4388 return (tetrahedron *) NULL;
4390 }
while ((newtetrahedron[4] == (tetrahedron) NULL) ||
4391 ((point) newtetrahedron[7] == dummypoint));
4392 return newtetrahedron;
4395 tetgenmesh::tetrahedron* tetgenmesh::alltetrahedrontraverse()
4397 tetrahedron *newtetrahedron;
4400 newtetrahedron = (tetrahedron *) tetrahedrons->traverse();
4401 if (newtetrahedron == (tetrahedron *) NULL) {
4402 return (tetrahedron *) NULL;
4404 }
while (newtetrahedron[4] == (tetrahedron) NULL);
4405 return newtetrahedron;
4415 void tetgenmesh::shellfacedealloc(memorypool *pool, shellface *dyingsh)
4419 dyingsh[3] = (shellface) NULL;
4420 pool->dealloc((
void *) dyingsh);
4430 tetgenmesh::shellface* tetgenmesh::shellfacetraverse(memorypool *pool)
4432 shellface *newshellface;
4435 newshellface = (shellface *) pool->traverse();
4436 if (newshellface == (shellface *) NULL) {
4437 return (shellface *) NULL;
4439 }
while (newshellface[3] == (shellface) NULL);
4440 return newshellface;
4450 void tetgenmesh::pointdealloc(point dyingpoint)
4454 setpointtype(dyingpoint, DEADVERTEX);
4455 points->dealloc((
void *) dyingpoint);
4464 tetgenmesh::point tetgenmesh::pointtraverse()
4469 newpoint = (point) points->traverse();
4470 if (newpoint == (point) NULL) {
4471 return (point) NULL;
4473 }
while (pointtype(newpoint) == DEADVERTEX);
4483 void tetgenmesh::maketetrahedron(triface *newtet)
4485 newtet->tet = (tetrahedron *) tetrahedrons->alloc();
4488 newtet->tet[0] = NULL;
4489 newtet->tet[1] = NULL;
4490 newtet->tet[2] = NULL;
4491 newtet->tet[3] = NULL;
4493 newtet->tet[4] = NULL;
4494 newtet->tet[5] = NULL;
4495 newtet->tet[6] = NULL;
4496 newtet->tet[7] = NULL;
4498 newtet->tet[8] = NULL;
4499 newtet->tet[9] = NULL;
4501 setelemmarker(newtet->tet, 0);
4502 for (
int i = 0; i < numelemattrib; i++) {
4503 setelemattribute(newtet->tet, i, 0.0);
4506 setvolumebound(newtet->tet, -1.0);
4520 void tetgenmesh::makeshellface(memorypool *pool, face *newface)
4522 newface->sh = (shellface *) pool->alloc();
4525 newface->sh[0] = NULL;
4526 newface->sh[1] = NULL;
4527 newface->sh[2] = NULL;
4529 newface->sh[3] = NULL;
4530 newface->sh[4] = NULL;
4531 newface->sh[5] = NULL;
4533 newface->sh[6] = NULL;
4534 newface->sh[7] = NULL;
4535 newface->sh[8] = NULL;
4537 newface->sh[9] = NULL;
4538 newface->sh[10] = NULL;
4539 if (checkconstraints) {
4541 setareabound(*newface, 0.0);
4544 setshellmark(*newface, 0);
4546 ((
int *) (newface->sh))[shmarkindex + 1] = 0;
4547 if (useinsertradius) {
4548 setfacetindex(*newface, 0);
4560 void tetgenmesh::makepoint(point* pnewpoint,
enum verttype vtype)
4564 *pnewpoint = (point) points->alloc();
4567 for (i = 0; i < numpointattrib; i++) {
4568 (*pnewpoint)[3 + i] = 0.0;
4571 for (i = 0; i < sizeoftensor; i++) {
4572 (*pnewpoint)[pointmtrindex + i] = 0.0;
4574 setpoint2tet(*pnewpoint, NULL);
4575 setpoint2ppt(*pnewpoint, NULL);
4576 if (b->plc || b->refine) {
4578 setpoint2sh(*pnewpoint, NULL);
4579 if (b->metric && (bgm != NULL)) {
4580 setpoint2bgmtet(*pnewpoint, NULL);
4584 setpointmark(*pnewpoint, (
int) (points->items) - (!in->firstnumber));
4586 ((
int *) (*pnewpoint))[pointmarkindex + 1] = 0;
4588 setpointtype(*pnewpoint, vtype);
4602 void tetgenmesh::initializepools()
4604 int pointsize = 0, elesize = 0, shsize = 0;
4608 printf(
" Initializing memorypools.\n");
4609 printf(
" tetrahedron per block: %d.\n", b->tetrahedraperblock);
4617 numpointattrib = in->numberofpointattributes;
4619 if (bgm->in->numberofpointattributes > numpointattrib) {
4620 numpointattrib = bgm->in->numberofpointattributes;
4623 if (addin != NULL) {
4624 if (addin->numberofpointattributes > numpointattrib) {
4625 numpointattrib = addin->numberofpointattributes;
4628 if (b->weighted || b->flipinsert) {
4631 if (numpointattrib == 0) {
4637 if (in->segmentconstraintlist || in->facetconstraintlist) {
4638 checkconstraints = 1;
4640 if (b->plc || b->refine) {
4643 if (!b->nobisect || checkconstraints) {
4644 useinsertradius = 1;
4652 pointmtrindex = 5 + numpointattrib;
4655 pointparamindex = pointmtrindex - 2;
4657 pointmtrindex = 3 + numpointattrib;
4664 sizeoftensor = (bgm->in != (
tetgenio *) NULL) ?
4665 bgm->in->numberofpointmtrs : in->numberofpointmtrs;
4668 sizeoftensor = in->numberofpointmtrs;
4671 sizeoftensor = (sizeoftensor > 0) ? sizeoftensor : 1;
4674 sizeoftensor = b->quality ? 1 : 0;
4676 if (useinsertradius) {
4681 pointinsradiusindex = pointmtrindex + sizeoftensor - 1;
4685 point2simindex = ((pointmtrindex + sizeoftensor) *
sizeof(REAL)
4686 +
sizeof(tetrahedron) - 1) /
sizeof(tetrahedron);
4687 if (b->plc || b->refine || b->voroout) {
4692 if (b->metric && (bgm != (
tetgenmesh *) NULL)) {
4694 pointsize = (point2simindex + 4) *
sizeof(tetrahedron);
4696 pointsize = (point2simindex + 3) *
sizeof(tetrahedron);
4702 pointsize = (point2simindex + 2) *
sizeof(tetrahedron);
4706 pointmarkindex = (pointsize +
sizeof(int) - 1) /
sizeof(int);
4711 pointsize = (pointmarkindex + 2 + (b->psc ? 1 : 0)) *
sizeof(tetrahedron);
4714 points =
new memorypool(pointsize, b->vertexperblock,
sizeof(REAL), 0);
4717 printf(
" Size of a point: %d bytes.\n", points->itembytes);
4721 dummypoint = (point)
new char[pointsize];
4723 dummypoint[0] = 0.0;
4724 dummypoint[1] = 0.0;
4725 dummypoint[2] = 0.0;
4726 for (i = 0; i < numpointattrib; i++) {
4727 dummypoint[3 + i] = 0.0;
4730 for (i = 0; i < sizeoftensor; i++) {
4731 dummypoint[pointmtrindex + i] = 0.0;
4733 setpoint2tet(dummypoint, NULL);
4734 setpoint2ppt(dummypoint, NULL);
4735 if (b->plc || b->psc || b->refine) {
4737 setpoint2sh(dummypoint, NULL);
4738 if (b->metric && (bgm != NULL)) {
4739 setpoint2bgmtet(dummypoint, NULL);
4743 setpointmark(dummypoint, -1);
4745 ((
int *) (dummypoint))[pointmarkindex + 1] = 0;
4747 setpointtype(dummypoint, UNUSEDVERTEX);
4765 elesize = 12 *
sizeof(tetrahedron);
4769 if (!(
sizeof(
int) <=
sizeof(tetrahedron)) ||
4770 ((
sizeof(tetrahedron) %
sizeof(
int)))) {
4771 terminatetetgen(
this, 2);
4773 elemmarkerindex = (elesize -
sizeof(tetrahedron)) /
sizeof(int);
4777 numelemattrib = in->numberoftetrahedronattributes + (b->regionattrib > 0);
4781 elemattribindex = (elesize +
sizeof(REAL) - 1) /
sizeof(REAL);
4784 volumeboundindex = elemattribindex + numelemattrib;
4788 elesize = (volumeboundindex + 1) *
sizeof(REAL);
4789 }
else if (numelemattrib > 0) {
4790 elesize = volumeboundindex *
sizeof(REAL);
4795 tetrahedrons =
new memorypool(elesize, b->tetrahedraperblock,
sizeof(
void *),
4799 printf(
" Size of a tetrahedron: %d (%d) bytes.\n", elesize,
4800 tetrahedrons->itembytes);
4803 if (b->plc || b->refine) {
4807 shsize = 11 *
sizeof(shellface);
4810 areaboundindex = (shsize +
sizeof(REAL) - 1) /
sizeof(REAL);
4813 if (checkconstraints) {
4814 shsize = (areaboundindex + 1) *
sizeof(REAL);
4816 shsize = areaboundindex *
sizeof(REAL);
4820 shmarkindex = (shsize +
sizeof(int) - 1) /
sizeof(int);
4824 shsize = (shmarkindex + 2 + useinsertradius) *
sizeof(shellface);
4829 subfaces =
new memorypool(shsize, b->shellfaceperblock,
sizeof(
void *), 8);
4832 printf(
" Size of a shellface: %d (%d) bytes.\n", shsize,
4833 subfaces->itembytes);
4838 subsegs =
new memorypool(shsize, b->shellfaceperblock,
sizeof(
void *), 8);
4841 tet2segpool =
new memorypool(6 *
sizeof(shellface), b->shellfaceperblock,
4844 tet2subpool =
new memorypool(4 *
sizeof(shellface), b->shellfaceperblock,
4848 subsegstack =
new arraypool(
sizeof(face), 10);
4849 subfacstack =
new arraypool(
sizeof(face), 10);
4850 subvertstack =
new arraypool(
sizeof(point), 8);
4853 caveshlist =
new arraypool(
sizeof(face), 8);
4854 caveshbdlist =
new arraypool(
sizeof(face), 8);
4855 cavesegshlist =
new arraypool(
sizeof(face), 4);
4857 cavetetshlist =
new arraypool(
sizeof(face), 8);
4858 cavetetseglist =
new arraypool(
sizeof(face), 8);
4859 caveencshlist =
new arraypool(
sizeof(face), 8);
4860 caveencseglist =
new arraypool(
sizeof(face), 8);
4864 flippool =
new memorypool(
sizeof(badface), 1024,
sizeof(
void *), 0);
4865 unflipqueue =
new arraypool(
sizeof(badface), 10);
4868 cavetetlist =
new arraypool(
sizeof(triface), 10);
4869 cavebdrylist =
new arraypool(
sizeof(triface), 10);
4870 caveoldtetlist =
new arraypool(
sizeof(triface), 10);
4871 cavetetvertlist =
new arraypool(
sizeof(point), 10);
4883 REAL tetgenmesh::PI = 3.14159265358979323846264338327950288419716939937510582;
4901 REAL tetgenmesh::insphere_s(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe)
4905 sign = insphere(pa, pb, pc, pd, pe);
4911 point pt[5], swappt;
4930 for (i = 0; i < n; i++) {
4931 if (pointmark(pt[i]) > pointmark(pt[i+1])) {
4932 swappt = pt[i]; pt[i] = pt[i+1]; pt[i+1] = swappt;
4937 }
while (count > 0);
4939 oriA = orient3d(pt[1], pt[2], pt[3], pt[4]);
4942 if ((swaps % 2) != 0) oriA = -oriA;
4946 oriB = -orient3d(pt[0], pt[2], pt[3], pt[4]);
4948 terminatetetgen(
this, 2);
4951 if ((swaps % 2) != 0) oriB = -oriB;
4972 REAL tetgenmesh::orient4d_s(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe,
4973 REAL aheight, REAL bheight, REAL cheight,
4974 REAL dheight, REAL eheight)
4978 sign = orient4d(pa, pb, pc, pd, pe,
4979 aheight, bheight, cheight, dheight, eheight);
4985 point pt[5], swappt;
5004 for (i = 0; i < n; i++) {
5005 if (pointmark(pt[i]) > pointmark(pt[i+1])) {
5006 swappt = pt[i]; pt[i] = pt[i+1]; pt[i+1] = swappt;
5011 }
while (count > 0);
5013 oriA = orient3d(pt[1], pt[2], pt[3], pt[4]);
5016 if ((swaps % 2) != 0) oriA = -oriA;
5020 oriB = -orient3d(pt[0], pt[2], pt[3], pt[4]);
5022 terminatetetgen(
this, 2);
5025 if ((swaps % 2) != 0) oriB = -oriB;
5051 #define SETVECTOR3(V, a0, a1, a2) (V)[0] = (a0); (V)[1] = (a1); (V)[2] = (a2) 5053 #define SWAP2(a0, a1, tmp) (tmp) = (a0); (a0) = (a1); (a1) = (tmp) 5055 int tetgenmesh::tri_edge_2d(point A, point B, point C, point P, point Q,
5056 point R,
int level,
int *types,
int *pos)
5062 REAL s1, s2, s3, s4;
5070 facenormal(A, B, C, n, 1, NULL);
5071 len = sqrt(dot(n, n));
5076 len = distance(A, B);
5077 len += distance(B, C);
5078 len += distance(C, A);
5081 R[0] = A[0] + len * n[0];
5082 R[1] = A[1] + len * n[1];
5083 R[2] = A[2] + len * n[2];
5094 sA = orient3d(P, Q, R, A);
5095 sB = orient3d(P, Q, R, B);
5096 sC = orient3d(P, Q, R, C);
5106 SETVECTOR3(U, A, B, C);
5107 SETVECTOR3(V, P, Q, R);
5108 SETVECTOR3(pu, 0, 1, 2);
5109 SETVECTOR3(pv, 0, 1, 2);
5112 SETVECTOR3(U, A, B, C);
5113 SETVECTOR3(V, P, Q, R);
5114 SETVECTOR3(pu, 0, 1, 2);
5115 SETVECTOR3(pv, 0, 1, 2);
5122 SETVECTOR3(U, C, A, B);
5123 SETVECTOR3(V, P, Q, R);
5124 SETVECTOR3(pu, 2, 0, 1);
5125 SETVECTOR3(pv, 0, 1, 2);
5129 SETVECTOR3(U, B, C, A);
5130 SETVECTOR3(V, Q, P, R);
5131 SETVECTOR3(pu, 1, 2, 0);
5132 SETVECTOR3(pv, 1, 0, 2);
5135 SETVECTOR3(U, C, A, B);
5136 SETVECTOR3(V, P, Q, R);
5137 SETVECTOR3(pu, 2, 0, 1);
5138 SETVECTOR3(pv, 0, 1, 2);
5144 SETVECTOR3(U, C, A, B);
5145 SETVECTOR3(V, P, Q, R);
5146 SETVECTOR3(pu, 2, 0, 1);
5147 SETVECTOR3(pv, 0, 1, 2);
5151 SETVECTOR3(U, B, C, A);
5152 SETVECTOR3(V, Q, P, R);
5153 SETVECTOR3(pu, 1, 2, 0);
5154 SETVECTOR3(pv, 1, 0, 2);
5157 SETVECTOR3(U, B, C, A);
5158 SETVECTOR3(V, Q, P, R);
5159 SETVECTOR3(pu, 1, 2, 0);
5160 SETVECTOR3(pv, 1, 0, 2);
5170 SETVECTOR3(U, B, C, A);
5171 SETVECTOR3(V, P, Q, R);
5172 SETVECTOR3(pu, 1, 2, 0);
5173 SETVECTOR3(pv, 0, 1, 2);
5177 SETVECTOR3(U, C, A, B);
5178 SETVECTOR3(V, Q, P, R);
5179 SETVECTOR3(pu, 2, 0, 1);
5180 SETVECTOR3(pv, 1, 0, 2);
5183 SETVECTOR3(U, C, A, B);
5184 SETVECTOR3(V, Q, P, R);
5185 SETVECTOR3(pu, 2, 0, 1);
5186 SETVECTOR3(pv, 1, 0, 2);
5193 SETVECTOR3(U, A, B, C);
5194 SETVECTOR3(V, Q, P, R);
5195 SETVECTOR3(pu, 0, 1, 2);
5196 SETVECTOR3(pv, 1, 0, 2);
5202 SETVECTOR3(U, A, B, C);
5203 SETVECTOR3(V, Q, P, R);
5204 SETVECTOR3(pu, 0, 1, 2);
5205 SETVECTOR3(pv, 1, 0, 2);
5211 SETVECTOR3(U, B, C, A);
5212 SETVECTOR3(V, P, Q, R);
5213 SETVECTOR3(pu, 1, 2, 0);
5214 SETVECTOR3(pv, 0, 1, 2);
5218 SETVECTOR3(U, C, A, B);
5219 SETVECTOR3(V, Q, P, R);
5220 SETVECTOR3(pu, 2, 0, 1);
5221 SETVECTOR3(pv, 1, 0, 2);
5224 SETVECTOR3(U, B, C, A);
5225 SETVECTOR3(V, P, Q, R);
5226 SETVECTOR3(pu, 1, 2, 0);
5227 SETVECTOR3(pv, 0, 1, 2);
5236 SETVECTOR3(U, B, C, A);
5237 SETVECTOR3(V, P, Q, R);
5238 SETVECTOR3(pu, 1, 2, 0);
5239 SETVECTOR3(pv, 0, 1, 2);
5243 SETVECTOR3(U, A, B, C);
5244 SETVECTOR3(V, P, Q, R);
5245 SETVECTOR3(pu, 0, 1, 2);
5246 SETVECTOR3(pv, 0, 1, 2);
5249 SETVECTOR3(U, C, A, B);
5250 SETVECTOR3(V, Q, P, R);
5251 SETVECTOR3(pu, 2, 0, 1);
5252 SETVECTOR3(pv, 1, 0, 2);
5259 SETVECTOR3(U, A, B, C);
5260 SETVECTOR3(V, Q, P, R);
5261 SETVECTOR3(pu, 0, 1, 2);
5262 SETVECTOR3(pv, 1, 0, 2);
5266 SETVECTOR3(U, B, C, A);
5267 SETVECTOR3(V, Q, P, R);
5268 SETVECTOR3(pu, 1, 2, 0);
5269 SETVECTOR3(pv, 1, 0, 2);
5272 SETVECTOR3(U, C, A, B);
5273 SETVECTOR3(V, P, Q, R);
5274 SETVECTOR3(pu, 2, 0, 1);
5275 SETVECTOR3(pv, 0, 1, 2);
5281 SETVECTOR3(U, A, B, C);
5282 SETVECTOR3(V, Q, P, R);
5283 SETVECTOR3(pu, 0, 1, 2);
5284 SETVECTOR3(pv, 1, 0, 2);
5288 SETVECTOR3(U, A, B, C);
5289 SETVECTOR3(V, P, Q, R);
5290 SETVECTOR3(pu, 0, 1, 2);
5291 SETVECTOR3(pv, 0, 1, 2);
5296 SETVECTOR3(U, A, B, C);
5297 SETVECTOR3(V, P, Q, R);
5298 SETVECTOR3(pu, 0, 1, 2);
5299 SETVECTOR3(pv, 0, 1, 2);
5308 s1 = orient3d(U[0], U[2], R, V[1]);
5309 s2 = orient3d(U[1], U[2], R, V[0]);
5326 types[0] = (int) SHAREVERT;
5329 types[1] = (int) DISJOINT;
5333 types[0] = (int) SHAREVERT;
5336 types[1] = (int) DISJOINT;
5339 types[0] = (int) ACROSSVERT;
5342 types[1] = (int) DISJOINT;
5348 s3 = orient3d(U[0], U[2], R, V[0]);
5349 s4 = orient3d(U[1], U[2], R, V[1]);
5356 types[0] = (int) ACROSSEDGE;
5359 types[1] = (int) TOUCHFACE;
5365 types[0] = (int) ACROSSEDGE;
5368 types[1] = (int) TOUCHEDGE;
5373 types[0] = (int) ACROSSEDGE;
5376 types[1] = (int) ACROSSEDGE;
5385 types[0] = (int) TOUCHEDGE;
5388 types[1] = (int) TOUCHFACE;
5394 types[0] = (int) TOUCHEDGE;
5397 types[1] = (int) TOUCHEDGE;
5402 types[0] = (int) TOUCHEDGE;
5405 types[1] = (int) ACROSSEDGE;
5414 types[0] = (int) TOUCHFACE;
5417 types[1] = (int) TOUCHFACE;
5423 types[0] = (int) TOUCHFACE;
5426 types[1] = (int) TOUCHEDGE;
5431 types[0] = (int) TOUCHFACE;
5434 types[1] = (int) ACROSSEDGE;
5441 types[0] = (int) TOUCHEDGE;
5444 types[1] = (int) DISJOINT;
5450 types[0] = (int) TOUCHEDGE;
5453 types[1] = (int) DISJOINT;
5455 }
else if (z1 == 2) {
5460 types[0] = (int) ACROSSVERT;
5463 types[1] = (int) TOUCHFACE;
5469 types[0] = (int) ACROSSVERT;
5472 types[1] = (int) TOUCHEDGE;
5477 types[0] = (int) ACROSSVERT;
5480 types[1] = (int) ACROSSEDGE;
5489 types[0] = (int) SHAREVERT;
5492 types[1] = (int) TOUCHFACE;
5498 types[0] = (int) SHAREVERT;
5501 types[1] = (int) TOUCHEDGE;
5506 types[0] = (int) SHAREVERT;
5509 types[1] = (int) ACROSSEDGE;
5518 types[0] = (int) TOUCHFACE;
5521 types[0] = (int) TOUCHFACE;
5527 types[0] = (int) TOUCHFACE;
5530 types[0] = (int) TOUCHEDGE;
5535 types[0] = (int) TOUCHFACE;
5538 types[0] = (int) ACROSSEDGE;
5545 types[0] = (int) TOUCHEDGE;
5548 types[1] = (int) DISJOINT;
5554 types[0] = (int) SHAREVERT;
5557 types[1] = (int) DISJOINT;
5559 }
else if (z1 == 3) {
5564 types[0] = (int) ACROSSVERT;
5567 types[1] = (int) TOUCHEDGE;
5573 types[0] = (int) ACROSSVERT;
5576 types[1] = (int) SHAREVERT;
5581 types[0] = (int) ACROSSVERT;
5584 types[1] = (int) ACROSSVERT;
5593 types[0] = (int) SHAREVERT;
5596 types[1] = (int) TOUCHEDGE;
5602 types[0] = (int) SHAREEDGE;
5605 types[1] = (int) DISJOINT;
5608 types[0] = (int) SHAREVERT;
5611 types[1] = (int) ACROSSVERT;
5620 types[0] = (int) TOUCHEDGE;
5623 types[1] = (int) TOUCHEDGE;
5629 types[0] = (int) TOUCHEDGE;
5632 types[1] = (int) SHAREVERT;
5637 types[0] = (int) TOUCHEDGE;
5640 types[1] = (int) ACROSSVERT;
5647 types[0] = (int) SHAREVERT;
5650 types[1] = (int) DISJOINT;
5656 types[0] = (int) SHAREVERT;
5659 types[1] = (int) DISJOINT;
5666 int tetgenmesh::tri_edge_tail(point A,point B,point C,point P,point Q,point R,
5667 REAL sP,REAL sQ,
int level,
int *types,
int *pos)
5680 SETVECTOR3(U, A, B, C);
5681 SETVECTOR3(V, P, Q, R);
5682 SETVECTOR3(pu, 0, 1, 2);
5683 SETVECTOR3(pv, 0, 1, 2);
5686 SETVECTOR3(U, A, B, C);
5687 SETVECTOR3(V, P, Q, R);
5688 SETVECTOR3(pu, 0, 1, 2);
5689 SETVECTOR3(pv, 0, 1, 2);
5696 SETVECTOR3(U, A, B, C);
5697 SETVECTOR3(V, Q, P, R);
5698 SETVECTOR3(pu, 0, 1, 2);
5699 SETVECTOR3(pv, 1, 0, 2);
5705 SETVECTOR3(U, B, A, C);
5706 SETVECTOR3(V, P, Q, R);
5707 SETVECTOR3(pu, 1, 0, 2);
5708 SETVECTOR3(pv, 0, 1, 2);
5714 SETVECTOR3(U, A, B, C);
5715 SETVECTOR3(V, Q, P, R);
5716 SETVECTOR3(pu, 0, 1, 2);
5717 SETVECTOR3(pv, 1, 0, 2);
5721 SETVECTOR3(U, B, A, C);
5722 SETVECTOR3(V, Q, P, R);
5723 SETVECTOR3(pu, 1, 0, 2);
5724 SETVECTOR3(pv, 1, 0, 2);
5736 return tri_edge_2d(A, B, C, P, Q, R, level, types, pos);
5739 s1 = orient3d(U[0], U[1], V[0], V[1]);
5744 s2 = orient3d(U[1], U[2], V[0], V[1]);
5749 s3 = orient3d(U[2], U[0], V[0], V[1]);
5758 types[1] = (int) DISJOINT;
5765 types[0] = (int) ACROSSFACE;
5770 types[0] = (int) ACROSSEDGE;
5777 types[0] = (int) ACROSSEDGE;
5782 types[0] = (int) ACROSSVERT;
5791 types[0] = (int) ACROSSEDGE;
5796 types[0] = (int) ACROSSVERT;
5803 types[0] = (int) ACROSSVERT;
5814 types[0] = (int) TOUCHFACE;
5819 types[0] = (int) TOUCHEDGE;
5826 types[0] = (int) TOUCHEDGE;
5831 types[0] = (int) SHAREVERT;
5840 types[0] = (int) TOUCHEDGE;
5845 types[0] = (int) SHAREVERT;
5852 types[0] = (int) SHAREVERT;
5864 int tetgenmesh::tri_edge_test(point A, point B, point C, point P, point Q,
5865 point R,
int level,
int *types,
int *pos)
5870 sP = orient3d(A, B, C, P);
5871 sQ = orient3d(A, B, C, Q);
5873 return tri_edge_tail(A, B, C, P, Q, R, sP, sQ, level, types, pos);
5886 int tetgenmesh::tri_edge_inter_tail(REAL* A, REAL* B, REAL* C, REAL* P,
5887 REAL* Q, REAL s_p, REAL s_q)
5889 int types[2], pos[4];
5892 ni = tri_edge_tail(A, B, C, P, Q, NULL, s_p, s_q, 1, types, pos);
5897 if (types[0] == (
int) SHAREVERT) {
5898 return (
int) SHAREVERT;
5900 return (
int) INTERSECT;
5902 }
else if (ni == 4) {
5904 if (types[0] == (
int) SHAREVERT) {
5905 if (types[1] == (
int) DISJOINT) {
5906 return (
int) SHAREVERT;
5908 return (
int) INTERSECT;
5911 if (types[0] == (
int) SHAREEDGE) {
5912 return (
int) SHAREEDGE;
5914 return (
int) INTERSECT;
5920 return (
int) DISJOINT;
5923 int tetgenmesh::tri_tri_inter(REAL* A,REAL* B,REAL* C,REAL* O,REAL* P,REAL* Q)
5928 s_o = orient3d(A, B, C, O);
5929 s_p = orient3d(A, B, C, P);
5930 s_q = orient3d(A, B, C, Q);
5931 if ((s_o * s_p > 0.0) && (s_o * s_q > 0.0)) {
5936 s_a = orient3d(O, P, Q, A);
5937 s_b = orient3d(O, P, Q, B);
5938 s_c = orient3d(O, P, Q, C);
5939 if ((s_a * s_b > 0.0) && (s_a * s_c > 0.0)) {
5944 int abcop, abcpq, abcqo;
5947 abcop = tri_edge_inter_tail(A, B, C, O, P, s_o, s_p);
5948 if (abcop == (
int) INTERSECT) {
5949 return (
int) INTERSECT;
5950 }
else if (abcop == (
int) SHAREEDGE) {
5953 abcpq = tri_edge_inter_tail(A, B, C, P, Q, s_p, s_q);
5954 if (abcpq == (
int) INTERSECT) {
5955 return (
int) INTERSECT;
5956 }
else if (abcpq == (
int) SHAREEDGE) {
5959 abcqo = tri_edge_inter_tail(A, B, C, Q, O, s_q, s_o);
5960 if (abcqo == (
int) INTERSECT) {
5961 return (
int) INTERSECT;
5962 }
else if (abcqo == (
int) SHAREEDGE) {
5965 if (shareedge == 3) {
5967 return (
int) SHAREFACE;
5971 int opqab, opqbc, opqca;
5973 opqab = tri_edge_inter_tail(O, P, Q, A, B, s_a, s_b);
5974 if (opqab == (
int) INTERSECT) {
5975 return (
int) INTERSECT;
5977 opqbc = tri_edge_inter_tail(O, P, Q, B, C, s_b, s_c);
5978 if (opqbc == (
int) INTERSECT) {
5979 return (
int) INTERSECT;
5981 opqca = tri_edge_inter_tail(O, P, Q, C, A, s_c, s_a);
5982 if (opqca == (
int) INTERSECT) {
5983 return (
int) INTERSECT;
5988 if (abcop == (
int) SHAREEDGE) {
5990 return (
int) SHAREEDGE;
5992 if (abcpq == (
int) SHAREEDGE) {
5994 return (
int) SHAREEDGE;
5996 if (abcqo == (
int) SHAREEDGE) {
5998 return (
int) SHAREEDGE;
6002 if (abcop == (
int) SHAREVERT) {
6003 return (
int) SHAREVERT;
6005 if (abcpq == (
int) SHAREVERT) {
6007 return (
int) SHAREVERT;
6011 return (
int) DISJOINT;
6038 bool tetgenmesh::lu_decmp(REAL lu[4][4],
int n,
int* ps, REAL* d,
int N)
6041 REAL pivot, biggest, mult, tempf;
6047 for (i = N; i < n + N; i++) {
6050 for (j = N; j < n + N; j++)
6051 if (biggest < (tempf = fabs(lu[i][j])))
6054 scales[i] = 1.0 / biggest;
6062 for (k = N; k < n + N - 1; k++) {
6065 for (i = k; i < n + N; i++) {
6066 if (biggest < (tempf = fabs(lu[ps[i]][k]) * scales[ps[i]])) {
6071 if (biggest == 0.0) {
6074 if (pivotindex != k) {
6076 ps[k] = ps[pivotindex];
6082 pivot = lu[ps[k]][k];
6083 for (i = k + 1; i < n + N; i++) {
6084 lu[ps[i]][k] = mult = lu[ps[i]][k] / pivot;
6086 for (j = k + 1; j < n + N; j++)
6087 lu[ps[i]][j] -= mult * lu[ps[k]][j];
6093 return lu[ps[n + N - 1]][n + N - 1] != 0.0;
6111 void tetgenmesh::lu_solve(REAL lu[4][4],
int n,
int* ps, REAL* b,
int N)
6116 for (i = N; i < n + N; i++) X[i] = 0.0;
6119 for (i = N; i < n + N; i++) {
6121 for (j = N; j < i + N; j++)
6122 dot += lu[ps[i]][j] * X[j];
6123 X[i] = b[ps[i]] - dot;
6127 for (i = n + N - 1; i >= N; i--) {
6129 for (j = i + 1; j < n + N; j++)
6130 dot += lu[ps[i]][j] * X[j];
6131 X[i] = (X[i] - dot) / lu[ps[i]][i];
6134 for (i = N; i < n + N; i++) b[i] = X[i];
6149 REAL tetgenmesh::incircle3d(point pa, point pb, point pc, point pd)
6151 REAL area2[2], n1[3], n2[3], c[3];
6155 facenormal(pa, pb, pc, n1, 1, NULL);
6156 area2[0] = dot(n1, n1);
6157 facenormal(pb, pa, pd, n2, 1, NULL);
6158 area2[1] = dot(n2, n2);
6160 if (area2[0] > area2[1]) {
6162 circumsphere(pa, pb, pc, NULL, c, &r);
6163 d = distance(c, pd);
6167 circumsphere(pb, pa, pd, NULL, c, &r);
6168 d = distance(c, pc);
6176 if (fabs(sign) / r < b->epsilon) {
6200 void tetgenmesh::facenormal(point pa, point pb, point pc, REAL *n,
int pivot,
6203 REAL v1[3], v2[3], v3[3], *pv1, *pv2;
6206 v1[0] = pb[0] - pa[0];
6207 v1[1] = pb[1] - pa[1];
6208 v1[2] = pb[2] - pa[2];
6209 v2[0] = pa[0] - pc[0];
6210 v2[1] = pa[1] - pc[1];
6211 v2[2] = pa[2] - pc[2];
6216 v3[0] = pc[0] - pb[0];
6217 v3[1] = pc[1] - pb[1];
6218 v3[2] = pc[2] - pb[2];
6238 *lav = (sqrt(L1) + sqrt(L2) + sqrt(L3)) / 3.0;
6266 REAL tetgenmesh::shortdistance(REAL* p, REAL* e1, REAL* e2)
6271 v1[0] = e2[0] - e1[0];
6272 v1[1] = e2[1] - e1[1];
6273 v1[2] = e2[2] - e1[2];
6274 v2[0] = p[0] - e1[0];
6275 v2[1] = p[1] - e1[1];
6276 v2[2] = p[2] - e1[2];
6278 len = sqrt(dot(v1, v1));
6285 return sqrt(dot(v2, v2) - l_p * l_p);
6294 REAL tetgenmesh::triarea(REAL* pa, REAL* pb, REAL* pc)
6299 A[0][0] = pb[0] - pa[0];
6300 A[0][1] = pb[1] - pa[1];
6301 A[0][2] = pb[2] - pa[2];
6302 A[1][0] = pc[0] - pa[0];
6303 A[1][1] = pc[1] - pa[1];
6304 A[1][2] = pc[2] - pa[2];
6306 cross(A[0], A[1], A[2]);
6308 return 0.5 * sqrt(dot(A[2], A[2]));
6311 REAL tetgenmesh::orient3dfast(REAL *pa, REAL *pb, REAL *pc, REAL *pd)
6317 adx = pa[0] - pd[0];
6318 bdx = pb[0] - pd[0];
6319 cdx = pc[0] - pd[0];
6320 ady = pa[1] - pd[1];
6321 bdy = pb[1] - pd[1];
6322 cdy = pc[1] - pd[1];
6323 adz = pa[2] - pd[2];
6324 bdz = pb[2] - pd[2];
6325 cdz = pc[2] - pd[2];
6327 return adx * (bdy * cdz - bdz * cdy)
6328 + bdx * (cdy * adz - cdz * ady)
6329 + cdx * (ady * bdz - adz * bdy);
6345 REAL tetgenmesh::interiorangle(REAL* o, REAL* p1, REAL* p2, REAL* n)
6347 REAL v1[3], v2[3], np[3];
6348 REAL theta, costheta, lenlen;
6349 REAL ori, len1, len2;
6352 v1[0] = p1[0] - o[0];
6353 v1[1] = p1[1] - o[1];
6354 v1[2] = p1[2] - o[2];
6355 v2[0] = p2[0] - o[0];
6356 v2[1] = p2[1] - o[1];
6357 v2[2] = p2[2] - o[2];
6358 len1 = sqrt(dot(v1, v1));
6359 len2 = sqrt(dot(v2, v2));
6360 lenlen = len1 * len2;
6362 costheta = dot(v1, v2) / lenlen;
6363 if (costheta > 1.0) {
6365 }
else if (costheta < -1.0) {
6368 theta = acos(costheta);
6371 np[0] = o[0] + n[0];
6372 np[1] = o[1] + n[1];
6373 np[2] = o[2] + n[2];
6375 ori = orient3d(p1, o, np, p2);
6377 theta = 2 * PI - theta;
6390 void tetgenmesh::projpt2edge(REAL* p, REAL* e1, REAL* e2, REAL* prj)
6395 v1[0] = e2[0] - e1[0];
6396 v1[1] = e2[1] - e1[1];
6397 v1[2] = e2[2] - e1[2];
6398 v2[0] = p[0] - e1[0];
6399 v2[1] = p[1] - e1[1];
6400 v2[2] = p[2] - e1[2];
6402 len = sqrt(dot(v1, v1));
6408 prj[0] = e1[0] + l_p * v1[0];
6409 prj[1] = e1[1] + l_p * v1[1];
6410 prj[2] = e1[2] + l_p * v1[2];
6419 void tetgenmesh::projpt2face(REAL* p, REAL* f1, REAL* f2, REAL* f3, REAL* prj)
6421 REAL fnormal[3], v1[3];
6425 facenormal(f1, f2, f3, fnormal, 1, NULL);
6426 len = sqrt(fnormal[0]*fnormal[0] + fnormal[1]*fnormal[1] +
6427 fnormal[2]*fnormal[2]);
6432 v1[0] = p[0] - f1[0];
6433 v1[1] = p[1] - f1[1];
6434 v1[2] = p[2] - f1[2];
6436 dist = dot(fnormal, v1);
6439 prj[0] = p[0] - dist * fnormal[0];
6440 prj[1] = p[1] - dist * fnormal[1];
6441 prj[2] = p[2] - dist * fnormal[2];
6455 bool tetgenmesh::tetalldihedral(point pa, point pb, point pc, point pd,
6456 REAL* cosdd, REAL* cosmaxd, REAL* cosmind)
6458 REAL N[4][3], vol, cosd, len;
6459 int f1 = 0, f2 = 0, i, j;
6464 tetallnormal(pa, pb, pc, pd, N, &vol);
6468 for (i = 0; i < 4; i++) {
6469 len = sqrt(dot(N[i], N[i]));
6471 for (j = 0; j < 3; j++) N[i][j] /= len;
6481 facenormal(pc, pb, pd, N[0], 1, NULL);
6482 facenormal(pa, pc, pd, N[1], 1, NULL);
6483 facenormal(pb, pa, pd, N[2], 1, NULL);
6484 facenormal(pa, pb, pc, N[3], 1, NULL);
6486 for (i = 0; i < 4; i++) {
6487 len = sqrt(dot(N[i], N[i]));
6489 for (j = 0; j < 3; j++) N[i][j] /= len;
6499 if (cosdd != NULL) {
6500 for (i = 0; i < 6; i++) {
6505 if (cosmaxd != NULL) {
6508 if (cosmind != NULL) {
6516 for (i = 0; i < 6; i++) {
6518 case 0: f1 = 0; f2 = 1;
break;
6519 case 1: f1 = 1; f2 = 2;
break;
6520 case 2: f1 = 2; f2 = 3;
break;
6521 case 3: f1 = 0; f2 = 3;
break;
6522 case 4: f1 = 2; f2 = 0;
break;
6523 case 5: f1 = 1; f2 = 3;
break;
6525 cosd = -dot(N[f1], N[f2]);
6526 if (cosd < -1.0) cosd = -1.0;
6527 if (cosd > 1.0) cosd = 1.0;
6528 if (cosdd) cosdd[i] = cosd;
6529 if (cosmaxd || cosmind) {
6531 if (cosmaxd) *cosmaxd = cosd;
6532 if (cosmind) *cosmind = cosd;
6534 if (cosmaxd) *cosmaxd = cosd < *cosmaxd ? cosd : *cosmaxd;
6535 if (cosmind) *cosmind = cosd > *cosmind ? cosd : *cosmind;
6553 void tetgenmesh::tetallnormal(point pa, point pb, point pc, point pd,
6554 REAL N[4][3], REAL* volume)
6556 REAL A[4][4], rhs[4], D;
6561 for (i = 0; i < 3; i++) A[0][i] = pa[i] - pd[i];
6562 for (i = 0; i < 3; i++) A[1][i] = pb[i] - pd[i];
6563 for (i = 0; i < 3; i++) A[2][i] = pc[i] - pd[i];
6566 if (lu_decmp(A, 3, indx, &D, 0)) {
6567 if (volume != NULL) {
6569 *volume = fabs((A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2])) / 6.0;
6571 for (j = 0; j < 3; j++) {
6572 for (i = 0; i < 3; i++) rhs[i] = 0.0;
6574 lu_solve(A, 3, indx, rhs, 0);
6575 for (i = 0; i < 3; i++) N[j][i] = rhs[i];
6578 for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
6581 if (volume != NULL) {
6596 REAL tetgenmesh::tetaspectratio(point pa, point pb, point pc, point pd)
6598 REAL V[6][3], edgelength[6], longlen;
6599 REAL vda[3], vdb[3], vdc[3];
6600 REAL N[4][3], A[4][4], rhs[4], D;
6601 REAL H[4], volume, minheightinv;
6606 for (i = 0; i < 3; i++) V[0][i] = pa[i] - pd[i];
6607 for (i = 0; i < 3; i++) V[1][i] = pb[i] - pd[i];
6608 for (i = 0; i < 3; i++) V[2][i] = pc[i] - pd[i];
6609 for (i = 0; i < 3; i++) V[3][i] = pb[i] - pa[i];
6610 for (i = 0; i < 3; i++) V[4][i] = pc[i] - pb[i];
6611 for (i = 0; i < 3; i++) V[5][i] = pa[i] - pc[i];
6614 for (i = 0; i < 6; i++) edgelength[i] = dot(V[i], V[i]);
6617 longlen = edgelength[0];
6618 for (i = 1; i < 6; i++) {
6619 longlen = edgelength[i] > longlen ? edgelength[i] : longlen;
6623 for (i = 0; i < 3; i++) A[0][i] = vda[i] = pa[i] - pd[i];
6624 for (i = 0; i < 3; i++) A[1][i] = vdb[i] = pb[i] - pd[i];
6625 for (i = 0; i < 3; i++) A[2][i] = vdc[i] = pc[i] - pd[i];
6627 lu_decmp(A, 3, indx, &D, 0);
6629 volume = (A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
6631 if (volume == 0.0)
return 1.0e+200;
6634 for (j = 0; j < 3; j++) {
6635 for (i = 0; i < 3; i++) rhs[i] = 0.0;
6637 lu_solve(A, 3, indx, rhs, 0);
6638 for (i = 0; i < 3; i++) N[j][i] = rhs[i];
6641 for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
6643 for (i = 0; i < 4; i++) {
6645 H[i] = sqrt(dot(N[i], N[i]));
6653 minheightinv = H[0];
6654 for (i = 1; i < 4; i++) {
6655 if (H[i] > minheightinv) minheightinv = H[i];
6658 return sqrt(longlen) * minheightinv;
6676 bool tetgenmesh::circumsphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd,
6677 REAL* cent, REAL* radius)
6679 REAL A[4][4], rhs[4], D;
6683 A[0][0] = pb[0] - pa[0];
6684 A[0][1] = pb[1] - pa[1];
6685 A[0][2] = pb[2] - pa[2];
6686 A[1][0] = pc[0] - pa[0];
6687 A[1][1] = pc[1] - pa[1];
6688 A[1][2] = pc[2] - pa[2];
6690 A[2][0] = pd[0] - pa[0];
6691 A[2][1] = pd[1] - pa[1];
6692 A[2][2] = pd[2] - pa[2];
6694 cross(A[0], A[1], A[2]);
6698 rhs[0] = 0.5 * dot(A[0], A[0]);
6699 rhs[1] = 0.5 * dot(A[1], A[1]);
6701 rhs[2] = 0.5 * dot(A[2], A[2]);
6708 if (!lu_decmp(A, 3, indx, &D, 0)) {
6709 if (radius != (REAL *) NULL) *radius = 0.0;
6712 lu_solve(A, 3, indx, rhs, 0);
6713 if (cent != (REAL *) NULL) {
6714 cent[0] = pa[0] + rhs[0];
6715 cent[1] = pa[1] + rhs[1];
6716 cent[2] = pa[2] + rhs[2];
6718 if (radius != (REAL *) NULL) {
6719 *radius = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
6734 bool tetgenmesh::orthosphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd,
6735 REAL aheight, REAL bheight, REAL cheight,
6736 REAL dheight, REAL* orthocent, REAL* radius)
6738 REAL A[4][4], rhs[4], D;
6742 A[0][0] = 1.0; A[0][1] = pa[0]; A[0][2] = pa[1]; A[0][3] = pa[2];
6743 A[1][0] = 1.0; A[1][1] = pb[0]; A[1][2] = pb[1]; A[1][3] = pb[2];
6744 A[2][0] = 1.0; A[2][1] = pc[0]; A[2][2] = pc[1]; A[2][3] = pc[2];
6745 A[3][0] = 1.0; A[3][1] = pd[0]; A[3][2] = pd[1]; A[3][3] = pd[2];
6748 rhs[0] = 0.5 * aheight;
6749 rhs[1] = 0.5 * bheight;
6750 rhs[2] = 0.5 * cheight;
6751 rhs[3] = 0.5 * dheight;
6755 if (!lu_decmp(A, 4, indx, &D, 0)) {
6756 if (radius != (REAL *) NULL) *radius = 0.0;
6759 lu_solve(A, 4, indx, rhs, 0);
6761 if (orthocent != (REAL *) NULL) {
6762 orthocent[0] = rhs[1];
6763 orthocent[1] = rhs[2];
6764 orthocent[2] = rhs[3];
6766 if (radius != (REAL *) NULL) {
6772 *radius = sqrt(rhs[1] * rhs[1] + rhs[2] * rhs[2] + rhs[3] * rhs[3]
6778 void tetgenmesh::tetcircumcenter(point tetorg, point tetdest, point tetfapex,
6779 point tettapex, REAL *circumcenter, REAL *radius)
6781 REAL xot, yot, zot, xdt, ydt, zdt, xft, yft, zft;
6782 REAL otlength, dtlength, ftlength;
6783 REAL xcrossdf, ycrossdf, zcrossdf;
6784 REAL xcrossfo, ycrossfo, zcrossfo;
6785 REAL xcrossod, ycrossod, zcrossod;
6792 xot = tetorg[0] - tettapex[0];
6793 yot = tetorg[1] - tettapex[1];
6794 zot = tetorg[2] - tettapex[2];
6795 xdt = tetdest[0] - tettapex[0];
6796 ydt = tetdest[1] - tettapex[1];
6797 zdt = tetdest[2] - tettapex[2];
6798 xft = tetfapex[0] - tettapex[0];
6799 yft = tetfapex[1] - tettapex[1];
6800 zft = tetfapex[2] - tettapex[2];
6802 otlength = xot * xot + yot * yot + zot * zot;
6803 dtlength = xdt * xdt + ydt * ydt + zdt * zdt;
6804 ftlength = xft * xft + yft * yft + zft * zft;
6806 xcrossdf = ydt * zft - yft * zdt;
6807 ycrossdf = zdt * xft - zft * xdt;
6808 zcrossdf = xdt * yft - xft * ydt;
6809 xcrossfo = yft * zot - yot * zft;
6810 ycrossfo = zft * xot - zot * xft;
6811 zcrossfo = xft * yot - xot * yft;
6812 xcrossod = yot * zdt - ydt * zot;
6813 ycrossod = zot * xdt - zdt * xot;
6814 zcrossod = xot * ydt - xdt * yot;
6823 denominator = 0.5 / orient3d(tetorg, tetdest, tetfapex, tettapex);
6829 xct = (otlength * xcrossdf + dtlength * xcrossfo + ftlength * xcrossod) *
6831 yct = (otlength * ycrossdf + dtlength * ycrossfo + ftlength * ycrossod) *
6833 zct = (otlength * zcrossdf + dtlength * zcrossfo + ftlength * zcrossod) *
6836 circumcenter[0] = xct + tettapex[0];
6837 circumcenter[1] = yct + tettapex[1];
6838 circumcenter[2] = zct + tettapex[2];
6840 if (radius != NULL) {
6841 *radius = sqrt(xct * xct + yct * yct + zct * zct);
6868 void tetgenmesh::planelineint(REAL* pa, REAL* pb, REAL* pc, REAL* e1, REAL* e2,
6871 REAL n[3], det, det1;
6874 facenormal(pa, pb, pc, n, 1, NULL);
6876 det = n[0] * (e2[0] - e1[0]) + n[1] * (e2[1] - e1[1])
6877 + n[2] * (e2[2] - e1[2]);
6880 det1 = n[0] * (pa[0] - e1[0]) + n[1] * (pa[1] - e1[1])
6881 + n[2] * (pa[2] - e1[2]);
6883 ip[0] = e1[0] + *u * (e2[0] - e1[0]);
6884 ip[1] = e1[1] + *u * (e2[1] - e1[1]);
6885 ip[2] = e1[2] + *u * (e2[2] - e1[2]);
6903 int tetgenmesh::linelineint(REAL* A, REAL* B, REAL* C, REAL* D, REAL* P,
6904 REAL* Q, REAL* tp, REAL* tq)
6906 REAL vab[3], vcd[3], vca[3];
6907 REAL vab_vab, vcd_vcd, vab_vcd;
6908 REAL vca_vab, vca_vcd;
6912 for (i = 0; i < 3; i++) {
6913 vab[i] = B[i] - A[i];
6914 vcd[i] = D[i] - C[i];
6915 vca[i] = A[i] - C[i];
6918 vab_vab = dot(vab, vab);
6919 vcd_vcd = dot(vcd, vcd);
6920 vab_vcd = dot(vab, vcd);
6922 det = vab_vab * vcd_vcd - vab_vcd * vab_vcd;
6924 eps = det / (fabs(vab_vab * vcd_vcd) + fabs(vab_vcd * vab_vcd));
6925 if (eps < b->epsilon) {
6929 vca_vab = dot(vca, vab);
6930 vca_vcd = dot(vca, vcd);
6932 *tp = (vcd_vcd * (- vca_vab) + vab_vcd * vca_vcd) / det;
6933 *tq = (vab_vcd * (- vca_vab) + vab_vab * vca_vcd) / det;
6935 for (i = 0; i < 3; i++) P[i] = A[i] + (*tp) * vab[i];
6936 for (i = 0; i < 3; i++) Q[i] = C[i] + (*tq) * vcd[i];
6962 REAL tetgenmesh::tetprismvol(REAL* p0, REAL* p1, REAL* p2, REAL* p3)
6964 REAL *p4, *p5, *p6, *p7;
6965 REAL w4, w5, w6, w7;
6980 vol[0] = orient4d(p5, p6, p4, p3, p7, w5, w6, w4, 0, w7);
6981 vol[1] = orient4d(p3, p6, p2, p0, p1, 0, w6, 0, 0, 0);
6982 vol[2] = orient4d(p4, p6, p3, p0, p1, w4, w6, 0, 0, 0);
6983 vol[3] = orient4d(p6, p5, p4, p3, p1, w6, w5, w4, 0, 0);
6985 return fabs(vol[0]) + fabs(vol[1]) + fabs(vol[2]) + fabs(vol[3]);
6994 bool tetgenmesh::calculateabovepoint(arraypool *facpoints, point *ppa,
6995 point *ppb, point *ppc)
6997 point *ppt, pa, pb, pc;
6998 REAL v1[3], v2[3], n[3];
6999 REAL lab, len, A, area;
7003 ppt = (point *) fastlookup(facpoints, 0);
7009 for (i = 1; i < facpoints->objects; i++) {
7010 ppt = (point *) fastlookup(facpoints, i);
7011 x = (*ppt)[0] - pa[0];
7012 y = (*ppt)[1] - pa[1];
7013 z = (*ppt)[2] - pa[2];
7014 len = x * x + y * y + z * z;
7023 printf(
"Warning: All points of a facet are coincident with %d.\n",
7030 v1[0] = pb[0] - pa[0];
7031 v1[1] = pb[1] - pa[1];
7032 v1[2] = pb[2] - pa[2];
7034 for (i = 1; i < facpoints->objects; i++) {
7035 ppt = (point *) fastlookup(facpoints, i);
7036 v2[0] = (*ppt)[0] - pa[0];
7037 v2[1] = (*ppt)[1] - pa[1];
7038 v2[2] = (*ppt)[2] - pa[2];
7049 printf(
"Warning: All points of a facet are collinaer with [%d, %d].\n",
7050 pointmark(pa), pointmark(pb));
7056 facenormal(pa, pb, pc, n, 1, NULL);
7057 len = sqrt(dot(n, n));
7062 dummypoint[0] = pa[0] + lab * n[0];
7063 dummypoint[1] = pa[1] + lab * n[1];
7064 dummypoint[2] = pa[2] + lab * n[2];
7084 void tetgenmesh::calculateabovepoint4(point pa, point pb, point pc, point pd)
7086 REAL n1[3], n2[3], *norm;
7087 REAL len, len1, len2;
7090 facenormal(pa, pb, pc, n1, 1, NULL);
7091 len1 = sqrt(dot(n1, n1));
7092 facenormal(pa, pb, pd, n2, 1, NULL);
7093 len2 = sqrt(dot(n2, n2));
7104 len = distance(pa, pb);
7105 dummypoint[0] = pa[0] + len * norm[0];
7106 dummypoint[1] = pa[1] + len * norm[1];
7107 dummypoint[2] = pa[2] + len * norm[2];
7120 void tetgenmesh::report_overlapping_facets(face *f1, face *f2, REAL dihedang)
7122 point pa, pb, pc, pd;
7130 printf(
"Found two %s self-intersecting facets.\n",
7131 dihedang > 0 ?
"nearly" :
"exactly");
7132 printf(
" 1st: [%d, %d, %d] #%d\n",
7133 pointmark(pa), pointmark(pb), pointmark(pc), shellmark(*f1));
7134 printf(
" 2nd: [%d, %d, %d] #%d\n",
7135 pointmark(pa), pointmark(pb), pointmark(pd), shellmark(*f2));
7137 printf(
"The dihedral angle between them is %g degree.\n",
7138 dihedang / PI * 180.0);
7139 printf(
"Hint: You may use -p/# to decrease the dihedral angle");
7140 printf(
" tolerance %g (degree).\n", b->facet_overlap_ang_tol);
7143 if (shellmark(*f1) != shellmark(*f2)) {
7145 printf(
"Found two overlapping facets.\n");
7147 printf(
"Found two duplicated facets.\n");
7149 printf(
" 1st: [%d, %d, %d] #%d\n",
7150 pointmark(pa), pointmark(pb), pointmark(pc), shellmark(*f1));
7151 printf(
" 2nd: [%d, %d, %d] #%d\n",
7152 pointmark(pa), pointmark(pb), pointmark(pd), shellmark(*f2));
7157 sevent.f_marker1 = shellmark(*f1);
7158 sevent.f_vertices1[0] = pointmark(pa);
7159 sevent.f_vertices1[1] = pointmark(pb);
7160 sevent.f_vertices1[2] = pointmark(pc);
7161 sevent.f_marker2 = shellmark(*f2);
7162 sevent.f_vertices2[0] = pointmark(pa);
7163 sevent.f_vertices2[1] = pointmark(pb);
7164 sevent.f_vertices2[2] = pointmark(pd);
7166 terminatetetgen(
this, 3);
7185 int tetgenmesh::report_selfint_edge(point e1, point e2, face *iedge,
7186 triface* itet,
enum interresult dir)
7188 point forg = NULL, fdest = NULL, fapex = NULL;
7189 int etype = 0, geomtag = 0, facemark = 0;
7191 if (iedge != NULL) {
7192 if (iedge->sh[5] != NULL) {
7196 fapex = sapex(*iedge);
7197 facemark = shellmark(*iedge);
7200 forg = farsorg(*iedge);
7201 fdest = farsdest(*iedge);
7204 spivot(*iedge, parentsh);
7205 if (parentsh.sh != NULL) {
7206 facemark = shellmark(parentsh);
7209 geomtag = shellmark(*iedge);
7212 if (dir == SHAREEDGE) {
7215 tsspivot1(*itet, colseg);
7217 if (colseg.sh != iedge->sh) {
7219 spivot(colseg, parentsh);
7220 printf(
"PLC Error: Two segments are overlapping.\n");
7221 printf(
" Segment 1: [%d, %d] #%d (%d)\n", pointmark(sorg(colseg)),
7222 pointmark(sdest(colseg)), shellmark(colseg),
7223 parentsh.sh ? shellmark(parentsh) : 0);
7224 printf(
" Segment 2: [%d, %d] #%d (%d)\n", pointmark(forg),
7225 pointmark(fdest), geomtag, facemark);
7227 sevent.f_marker1 = (parentsh.sh ? shellmark(parentsh) : 0);
7228 sevent.s_marker1 = shellmark(colseg);
7229 sevent.f_vertices1[0] = pointmark( sorg(colseg));
7230 sevent.f_vertices1[1] = pointmark(sdest(colseg));
7231 sevent.f_vertices1[2] = 0;
7232 sevent.f_marker2 = facemark;
7233 sevent.s_marker2 = geomtag;
7234 sevent.f_vertices2[0] = pointmark(forg);
7235 sevent.f_vertices2[1] = pointmark(fdest);
7236 sevent.f_vertices2[2] = 0;
7239 terminatetetgen(
this, 2);
7241 }
else if (etype == 2) {
7242 printf(
"PLC Error: A segment lies in a facet.\n");
7243 printf(
" Segment: [%d, %d] #%d\n", pointmark(sorg(colseg)),
7244 pointmark(sdest(colseg)), shellmark(colseg));
7245 printf(
" Facet: [%d,%d,%d] #%d\n", pointmark(forg),
7246 pointmark(fdest), pointmark(fapex), geomtag);
7248 sevent.f_marker1 = 0;
7249 sevent.s_marker1 = shellmark(colseg);
7250 sevent.f_vertices1[0] = pointmark( sorg(colseg));
7251 sevent.f_vertices1[1] = pointmark(sdest(colseg));
7252 sevent.f_vertices1[2] = 0;
7253 sevent.f_marker2 = geomtag;
7254 sevent.s_marker2 = 0;
7255 sevent.f_vertices2[0] = pointmark(forg);
7256 sevent.f_vertices2[1] = pointmark(fdest);
7257 sevent.f_vertices2[2] = pointmark(fapex);
7259 }
else if (dir == SHAREFACE) {
7262 tspivot(*itet, colface);
7264 if (colface.sh != iedge->sh) {
7265 printf(
"PLC Error: Two facets are overlapping.\n");
7266 printf(
" Facet 1: [%d,%d,%d] #%d\n", pointmark(forg),
7267 pointmark(fdest), pointmark(fapex), geomtag);
7268 printf(
" Facet 2: [%d,%d,%d] #%d\n", pointmark(sorg(colface)),
7269 pointmark(sdest(colface)), pointmark(sapex(colface)),
7270 shellmark(colface));
7272 sevent.f_marker1 = geomtag;
7273 sevent.s_marker1 = 0;
7274 sevent.f_vertices1[0] = pointmark(forg);
7275 sevent.f_vertices1[1] = pointmark(fdest);
7276 sevent.f_vertices1[2] = pointmark(fapex);
7277 sevent.f_marker2 = shellmark(colface);
7278 sevent.s_marker2 = 0;
7279 sevent.f_vertices2[0] = pointmark(sorg(colface));
7280 sevent.f_vertices2[1] = pointmark(sdest(colface));
7281 sevent.f_vertices2[2] = pointmark(sapex(colface));
7284 terminatetetgen(
this, 2);
7287 terminatetetgen(
this, 2);
7289 }
else if (dir == ACROSSVERT) {
7290 point pp = dest(*itet);
7291 if ((pointtype(pp) == RIDGEVERTEX) || (pointtype(pp) == FACETVERTEX)
7292 || (pointtype(pp) == VOLVERTEX)) {
7294 printf(
"PLC Error: A vertex lies in a segment.\n");
7295 printf(
" Vertex: [%d] (%g,%g,%g).\n",pointmark(pp),pp[0],pp[1],pp[2]);
7296 printf(
" Segment: [%d, %d] #%d (%d)\n", pointmark(forg),
7297 pointmark(fdest), geomtag, facemark);
7299 sevent.f_marker1 = 0;
7300 sevent.s_marker1 = 0;
7301 sevent.f_vertices1[0] = pointmark(pp);
7302 sevent.f_vertices1[1] = 0;
7303 sevent.f_vertices1[2] = 0;
7304 sevent.f_marker2 = facemark;
7305 sevent.s_marker2 = geomtag;
7306 sevent.f_vertices2[0] = pointmark(forg);
7307 sevent.f_vertices2[1] = pointmark(fdest);
7308 sevent.f_vertices2[2] = 0;
7309 sevent.int_point[0] = pp[0];
7310 sevent.int_point[1] = pp[1];
7311 sevent.int_point[2] = pp[2];
7312 }
else if (etype == 2) {
7313 printf(
"PLC Error: A vertex lies in a facet.\n");
7314 printf(
" Vertex: [%d] (%g,%g,%g).\n",pointmark(pp),pp[0],pp[1],pp[2]);
7315 printf(
" Facet: [%d,%d,%d] #%d\n", pointmark(forg), pointmark(fdest),
7316 pointmark(fapex), geomtag);
7318 sevent.f_marker1 = 0;
7319 sevent.s_marker1 = 0;
7320 sevent.f_vertices1[0] = pointmark(pp);
7321 sevent.f_vertices1[1] = 0;
7322 sevent.f_vertices1[2] = 0;
7323 sevent.f_marker2 = geomtag;
7324 sevent.s_marker2 = 0;
7325 sevent.f_vertices2[0] = pointmark(forg);
7326 sevent.f_vertices2[1] = pointmark(fdest);
7327 sevent.f_vertices2[2] = pointmark(fapex);
7328 sevent.int_point[0] = pp[0];
7329 sevent.int_point[1] = pp[1];
7330 sevent.int_point[2] = pp[2];
7332 }
else if (pointtype(pp) == FREESEGVERTEX) {
7333 face parentseg, parentsh;
7334 sdecode(point2sh(pp), parentseg);
7335 spivot(parentseg, parentsh);
7336 if (parentseg.sh != NULL) {
7337 point p1 = farsorg(parentseg);
7338 point p2 = farsdest(parentseg);
7340 printf(
"PLC Error: Two segments intersect at point (%g,%g,%g).\n",
7341 pp[0], pp[1], pp[2]);
7342 printf(
" Segment 1: [%d, %d], #%d (%d)\n", pointmark(forg),
7343 pointmark(fdest), geomtag, facemark);
7344 printf(
" Segment 2: [%d, %d], #%d (%d)\n", pointmark(p1),
7345 pointmark(p2), shellmark(parentseg),
7346 parentsh.sh ? shellmark(parentsh) : 0);
7348 sevent.f_marker1 = facemark;
7349 sevent.s_marker1 = geomtag;
7350 sevent.f_vertices1[0] = pointmark(forg);
7351 sevent.f_vertices1[1] = pointmark(fdest);
7352 sevent.f_vertices1[2] = 0;
7353 sevent.f_marker2 = (parentsh.sh ? shellmark(parentsh) : 0);
7354 sevent.s_marker2 = shellmark(parentseg);
7355 sevent.f_vertices2[0] = pointmark(p1);
7356 sevent.f_vertices2[1] = pointmark(p2);
7357 sevent.f_vertices2[2] = 0;
7358 sevent.int_point[0] = pp[0];
7359 sevent.int_point[1] = pp[1];
7360 sevent.int_point[2] = pp[2];
7361 }
else if (etype == 2) {
7362 printf(
"PLC Error: A segment and a facet intersect at point");
7363 printf(
" (%g,%g,%g).\n", pp[0], pp[1], pp[2]);
7364 printf(
" Segment: [%d, %d], #%d (%d)\n", pointmark(p1),
7365 pointmark(p2), shellmark(parentseg),
7366 parentsh.sh ? shellmark(parentsh) : 0);
7367 printf(
" Facet: [%d,%d,%d] #%d\n", pointmark(forg),
7368 pointmark(fdest), pointmark(fapex), geomtag);
7370 sevent.f_marker1 = (parentsh.sh ? shellmark(parentsh) : 0);
7371 sevent.s_marker1 = shellmark(parentseg);
7372 sevent.f_vertices1[0] = pointmark(p1);
7373 sevent.f_vertices1[1] = pointmark(p2);
7374 sevent.f_vertices1[2] = 0;
7375 sevent.f_marker2 = geomtag;
7376 sevent.s_marker2 = 0;
7377 sevent.f_vertices2[0] = pointmark(forg);
7378 sevent.f_vertices2[1] = pointmark(fdest);
7379 sevent.f_vertices2[2] = pointmark(fapex);
7380 sevent.int_point[0] = pp[0];
7381 sevent.int_point[1] = pp[1];
7382 sevent.int_point[2] = pp[2];
7385 terminatetetgen(
this, 2);
7387 }
else if (pointtype(pp) == FREEFACETVERTEX) {
7389 sdecode(point2sh(pp), parentsh);
7390 if (parentsh.sh != NULL) {
7391 point p1 = sorg(parentsh);
7392 point p2 = sdest(parentsh);
7393 point p3 = sapex(parentsh);
7395 printf(
"PLC Error: A segment and a facet intersect at point");
7396 printf(
" (%g,%g,%g).\n", pp[0], pp[1], pp[2]);
7397 printf(
" Segment : [%d, %d], #%d (%d)\n", pointmark(forg),
7398 pointmark(fdest), geomtag, facemark);
7399 printf(
" Facet : [%d, %d, %d] #%d.\n", pointmark(p1),
7400 pointmark(p2), pointmark(p3), shellmark(parentsh));
7402 sevent.f_marker1 = facemark;
7403 sevent.s_marker1 = geomtag;
7404 sevent.f_vertices1[0] = pointmark(forg);
7405 sevent.f_vertices1[1] = pointmark(fdest);
7406 sevent.f_vertices1[2] = 0;
7407 sevent.f_marker2 = shellmark(parentsh);
7408 sevent.s_marker2 = 0;
7409 sevent.f_vertices2[0] = pointmark(p1);
7410 sevent.f_vertices2[1] = pointmark(p2);
7411 sevent.f_vertices2[2] = pointmark(p3);
7412 sevent.int_point[0] = pp[0];
7413 sevent.int_point[1] = pp[1];
7414 sevent.int_point[2] = pp[2];
7415 }
else if (etype == 2) {
7416 printf(
"PLC Error: Two facets intersect at point (%g,%g,%g).\n",
7417 pp[0], pp[1], pp[2]);
7418 printf(
" Facet 1: [%d, %d, %d] #%d.\n", pointmark(forg),
7419 pointmark(fdest), pointmark(fapex), geomtag);
7420 printf(
" Facet 2: [%d, %d, %d] #%d.\n", pointmark(p1),
7421 pointmark(p2), pointmark(p3), shellmark(parentsh));
7423 sevent.f_marker1 = geomtag;
7424 sevent.s_marker1 = 0;
7425 sevent.f_vertices1[0] = pointmark(forg);
7426 sevent.f_vertices1[1] = pointmark(fdest);
7427 sevent.f_vertices1[2] = pointmark(fapex);
7428 sevent.f_marker2 = shellmark(parentsh);
7429 sevent.s_marker2 = 0;
7430 sevent.f_vertices2[0] = pointmark(p1);
7431 sevent.f_vertices2[1] = pointmark(p2);
7432 sevent.f_vertices2[2] = pointmark(p3);
7433 sevent.int_point[0] = pp[0];
7434 sevent.int_point[1] = pp[1];
7435 sevent.int_point[2] = pp[2];
7438 terminatetetgen(
this, 2);
7440 }
else if (pointtype(pp) == FREEVOLVERTEX) {
7444 terminatetetgen(
this, 2);
7446 terminatetetgen(
this, 2);
7448 terminatetetgen(
this, 3);
7449 }
else if (dir == ACROSSEDGE) {
7450 if (issubseg(*itet)) {
7452 tsspivot1(*itet, checkseg);
7454 spivot(checkseg, parentsh);
7456 point p1 = sorg(checkseg);
7457 point p2 = sdest(checkseg);
7458 REAL P[3], Q[3], tp = 0, tq = 0;
7459 linelineint(e1, e2, p1, p2, P, Q, &tp, &tq);
7461 printf(
"PLC Error: Two segments intersect at point (%g,%g,%g).\n",
7463 printf(
" Segment 1: [%d, %d] #%d (%d)\n", pointmark(forg),
7464 pointmark(fdest), geomtag, facemark);
7465 printf(
" Segment 2: [%d, %d] #%d (%d)\n", pointmark(p1),
7466 pointmark(p2), shellmark(checkseg),
7467 parentsh.sh ? shellmark(parentsh) : 0);
7469 sevent.f_marker1 = facemark;
7470 sevent.s_marker1 = geomtag;
7471 sevent.f_vertices1[0] = pointmark(forg);
7472 sevent.f_vertices1[1] = pointmark(fdest);
7473 sevent.f_vertices1[2] = 0;
7474 sevent.f_marker2 = (parentsh.sh ? shellmark(parentsh) : 0);
7475 sevent.s_marker2 = shellmark(checkseg);
7476 sevent.f_vertices2[0] = pointmark(p1);
7477 sevent.f_vertices2[1] = pointmark(p2);
7478 sevent.f_vertices2[2] = 0;
7479 sevent.int_point[0] = P[0];
7480 sevent.int_point[1] = P[1];
7481 sevent.int_point[2] = P[2];
7482 }
else if (etype == 2) {
7483 printf(
"PLC Error: A segment and a facet intersect at point");
7484 printf(
" (%g,%g,%g).\n", P[0], P[1], P[2]);
7485 printf(
" Segment: [%d, %d] #%d (%d)\n", pointmark(p1),
7486 pointmark(p2), shellmark(checkseg),
7487 parentsh.sh ? shellmark(parentsh) : 0);
7488 printf(
" Facet: [%d, %d, %d] #%d.\n", pointmark(forg),
7489 pointmark(fdest), pointmark(fapex), geomtag);
7491 sevent.f_marker1 = (parentsh.sh ? shellmark(parentsh) : 0);
7492 sevent.s_marker1 = shellmark(checkseg);
7493 sevent.f_vertices1[0] = pointmark(p1);
7494 sevent.f_vertices1[1] = pointmark(p2);
7495 sevent.f_vertices1[2] = 0;
7496 sevent.f_marker2 = geomtag;
7497 sevent.s_marker2 = 0;
7498 sevent.f_vertices2[0] = pointmark(forg);
7499 sevent.f_vertices2[1] = pointmark(fdest);
7500 sevent.f_vertices2[2] = pointmark(fapex);
7501 sevent.int_point[0] = P[0];
7502 sevent.int_point[1] = P[1];
7503 sevent.int_point[2] = P[2];
7505 terminatetetgen(
this, 3);
7507 }
else if (dir == ACROSSFACE) {
7508 if (issubface(*itet)) {
7510 tspivot(*itet, checksh);
7511 point p1 = sorg(checksh);
7512 point p2 = sdest(checksh);
7513 point p3 = sapex(checksh);
7515 planelineint(p1, p2, p3, e1, e2, ip, &u);
7517 printf(
"PLC Error: A segment and a facet intersect at point");
7518 printf(
" (%g,%g,%g).\n", ip[0], ip[1], ip[2]);
7519 printf(
" Segment: [%d, %d] #%d (%d)\n", pointmark(forg),
7520 pointmark(fdest), geomtag, facemark);
7521 printf(
" Facet: [%d, %d, %d] #%d.\n", pointmark(p1),
7522 pointmark(p2), pointmark(p3), shellmark(checksh));
7524 sevent.f_marker1 = facemark;
7525 sevent.s_marker1 = geomtag;
7526 sevent.f_vertices1[0] = pointmark(forg);
7527 sevent.f_vertices1[1] = pointmark(fdest);
7528 sevent.f_vertices1[2] = 0;
7529 sevent.f_marker2 = shellmark(checksh);
7530 sevent.s_marker2 = 0;
7531 sevent.f_vertices2[0] = pointmark(p1);
7532 sevent.f_vertices2[1] = pointmark(p2);
7533 sevent.f_vertices2[2] = pointmark(p3);
7534 sevent.int_point[0] = ip[0];
7535 sevent.int_point[1] = ip[1];
7536 sevent.int_point[2] = ip[2];
7537 }
else if (etype == 2) {
7538 printf(
"PLC Error: Two facets intersect at point (%g,%g,%g).\n",
7539 ip[0], ip[1], ip[2]);
7540 printf(
" Facet 1: [%d, %d, %d] #%d.\n", pointmark(forg),
7541 pointmark(fdest), pointmark(fapex), geomtag);
7542 printf(
" Facet 2: [%d, %d, %d] #%d.\n", pointmark(p1),
7543 pointmark(p2), pointmark(p3), shellmark(checksh));
7545 sevent.f_marker1 = geomtag;
7546 sevent.s_marker1 = 0;
7547 sevent.f_vertices1[0] = pointmark(forg);
7548 sevent.f_vertices1[1] = pointmark(fdest);
7549 sevent.f_vertices1[2] = pointmark(fapex);
7550 sevent.f_marker2 = shellmark(checksh);
7551 sevent.s_marker2 = 0;
7552 sevent.f_vertices2[0] = pointmark(p1);
7553 sevent.f_vertices2[1] = pointmark(p2);
7554 sevent.f_vertices2[2] = pointmark(p3);
7555 sevent.int_point[0] = ip[0];
7556 sevent.int_point[1] = ip[1];
7557 sevent.int_point[2] = ip[2];
7559 terminatetetgen(
this, 3);
7563 terminatetetgen(
this, 2);
7582 int tetgenmesh::report_selfint_face(point p1, point p2, point p3, face* sface,
7583 triface* iedge,
int intflag,
int* types,
int* poss)
7586 point e1 = NULL, e2 = NULL, e3 = NULL;
7587 int etype = 0, geomtag = 0, facemark = 0;
7589 geomtag = shellmark(*sface);
7591 if (issubface(*iedge)) {
7592 tspivot(*iedge, iface);
7598 }
else if (issubseg(*iedge)) {
7599 tsspivot1(*iedge, iface);
7600 e1 = farsorg(iface);
7601 e2 = farsdest(iface);
7604 spivot(iface, parentsh);
7605 facemark = shellmark(parentsh);
7607 terminatetetgen(
this, 2);
7613 planelineint(p1, p2, p3, e1, e2, ip, &u);
7614 if ((types[0] == (
int) ACROSSFACE) ||
7615 (types[0] == (
int) ACROSSEDGE)) {
7618 printf(
"PLC Error: A segment and a facet intersect at point");
7619 printf(
" (%g,%g,%g).\n", ip[0], ip[1], ip[2]);
7620 printf(
" Segment: [%d,%d] #%d (%d)\n", pointmark(e1), pointmark(e2),
7621 shellmark(iface), facemark);
7622 printf(
" Facet: [%d,%d,%d] #%d\n", pointmark(p1),
7623 pointmark(p2), pointmark(p3), geomtag);
7625 sevent.f_marker1 = facemark;
7626 sevent.s_marker1 = shellmark(iface);
7627 sevent.f_vertices1[0] = pointmark(e1);
7628 sevent.f_vertices1[1] = pointmark(e2);
7629 sevent.f_vertices1[2] = 0;
7630 sevent.f_marker2 = geomtag;
7631 sevent.s_marker2 = 0;
7632 sevent.f_vertices2[0] = pointmark(p1);
7633 sevent.f_vertices2[1] = pointmark(p2);
7634 sevent.f_vertices2[2] = pointmark(p3);
7635 sevent.int_point[0] = ip[0];
7636 sevent.int_point[1] = ip[1];
7637 sevent.int_point[2] = ip[2];
7639 printf(
"PLC Error: Two facets intersect at point");
7640 printf(
" (%g,%g,%g).\n", ip[0], ip[1], ip[2]);
7641 printf(
" Facet 1: [%d,%d,%d] #%d\n", pointmark(e1), pointmark(e2),
7642 pointmark(sorg(iface)), shellmark(iface));
7643 printf(
" Facet 2: [%d,%d,%d] #%d\n", pointmark(p1),
7644 pointmark(p2), pointmark(p3), geomtag);
7646 sevent.f_marker1 = shellmark(iface);
7647 sevent.s_marker1 = 0;
7648 sevent.f_vertices1[0] = pointmark(e1);
7649 sevent.f_vertices1[1] = pointmark(e2);
7650 sevent.f_vertices1[2] = pointmark(sorg(iface));
7651 sevent.f_marker2 = geomtag;
7652 sevent.s_marker2 = 0;
7653 sevent.f_vertices2[0] = pointmark(p1);
7654 sevent.f_vertices2[1] = pointmark(p2);
7655 sevent.f_vertices2[2] = pointmark(p3);
7656 sevent.int_point[0] = ip[0];
7657 sevent.int_point[1] = ip[1];
7658 sevent.int_point[2] = ip[2];
7660 }
else if (types[0] == (
int) ACROSSVERT) {
7662 point crosspt = NULL;
7665 }
else if (poss[0] == 1) {
7667 }
else if (poss[0] == 2) {
7670 terminatetetgen(
this, 2);
7672 if (!issteinerpoint(crosspt)) {
7674 printf(
"PLC Error: A vertex and a segment intersect at (%g,%g,%g)\n",
7675 crosspt[0], crosspt[1], crosspt[2]);
7676 printf(
" Vertex: #%d\n", pointmark(crosspt));
7677 printf(
" Segment: [%d,%d] #%d (%d)\n", pointmark(e1), pointmark(e2),
7678 shellmark(iface), facemark);
7680 sevent.f_marker1 = 0;
7681 sevent.s_marker1 = 0;
7682 sevent.f_vertices1[0] = pointmark(crosspt);
7683 sevent.f_vertices1[1] = 0;
7684 sevent.f_vertices1[2] = 0;
7685 sevent.f_marker2 = facemark;
7686 sevent.s_marker2 = shellmark(iface);
7687 sevent.f_vertices2[0] = pointmark(e1);
7688 sevent.f_vertices2[1] = pointmark(e2);
7689 sevent.f_vertices2[2] = 0;
7690 sevent.int_point[0] = crosspt[0];
7691 sevent.int_point[1] = crosspt[1];
7692 sevent.int_point[2] = crosspt[2];
7694 printf(
"PLC Error: A vertex and a facet intersect at (%g,%g,%g)\n",
7695 crosspt[0], crosspt[1], crosspt[2]);
7696 printf(
" Vertex: #%d\n", pointmark(crosspt));
7697 printf(
" Facet: [%d,%d,%d] #%d\n", pointmark(p1),
7698 pointmark(p2), pointmark(p3), geomtag);
7700 sevent.f_marker1 = 0;
7701 sevent.s_marker1 = 0;
7702 sevent.f_vertices1[0] = pointmark(crosspt);
7703 sevent.f_vertices1[1] = 0;
7704 sevent.f_vertices1[2] = 0;
7705 sevent.f_marker2 = geomtag;
7706 sevent.s_marker2 = 0;
7707 sevent.f_vertices2[0] = pointmark(p1);
7708 sevent.f_vertices2[1] = pointmark(p2);
7709 sevent.f_vertices2[2] = pointmark(p3);
7710 sevent.int_point[0] = crosspt[0];
7711 sevent.int_point[1] = crosspt[1];
7712 sevent.int_point[2] = crosspt[2];
7716 terminatetetgen(
this, 2);
7718 }
else if ((types[0] == (
int) TOUCHFACE) ||
7719 (types[0] == (
int) TOUCHEDGE)) {
7721 point touchpt = NULL;
7723 touchpt = org(*iedge);
7724 }
else if (poss[1] == 1) {
7725 touchpt = dest(*iedge);
7727 terminatetetgen(
this, 2);
7729 if (!issteinerpoint(touchpt)) {
7730 printf(
"PLC Error: A vertex and a facet intersect at (%g,%g,%g)\n",
7731 touchpt[0], touchpt[1], touchpt[2]);
7732 printf(
" Vertex: #%d\n", pointmark(touchpt));
7733 printf(
" Facet: [%d,%d,%d] #%d\n", pointmark(p1),
7734 pointmark(p2), pointmark(p3), geomtag);
7736 sevent.f_marker1 = 0;
7737 sevent.s_marker1 = 0;
7738 sevent.f_vertices1[0] = pointmark(touchpt);
7739 sevent.f_vertices1[1] = 0;
7740 sevent.f_vertices1[2] = 0;
7741 sevent.f_marker2 = geomtag;
7742 sevent.s_marker2 = 0;
7743 sevent.f_vertices2[0] = pointmark(p1);
7744 sevent.f_vertices2[1] = pointmark(p2);
7745 sevent.f_vertices2[2] = pointmark(p3);
7746 sevent.int_point[0] = touchpt[0];
7747 sevent.int_point[1] = touchpt[1];
7748 sevent.int_point[2] = touchpt[2];
7751 terminatetetgen(
this, 2);
7753 }
else if (types[0] == (
int) SHAREVERT) {
7754 terminatetetgen(
this, 2);
7756 terminatetetgen(
this, 2);
7758 }
else if (intflag == 4) {
7759 if (types[0] == (
int) SHAREFACE) {
7760 printf(
"PLC Error: Two facets are overlapping.\n");
7761 printf(
" Facet 1: [%d,%d,%d] #%d\n", pointmark(e1),
7762 pointmark(e2), pointmark(e3), facemark);
7763 printf(
" Facet 2: [%d,%d,%d] #%d\n", pointmark(p1),
7764 pointmark(p2), pointmark(p3), geomtag);
7766 sevent.f_marker1 = facemark;
7767 sevent.s_marker1 = 0;
7768 sevent.f_vertices1[0] = pointmark(e1);
7769 sevent.f_vertices1[1] = pointmark(e2);
7770 sevent.f_vertices1[2] = pointmark(e3);
7771 sevent.f_marker2 = geomtag;
7772 sevent.s_marker2 = 0;
7773 sevent.f_vertices2[0] = pointmark(p1);
7774 sevent.f_vertices2[1] = pointmark(p2);
7775 sevent.f_vertices2[2] = pointmark(p3);
7777 terminatetetgen(
this, 2);
7780 terminatetetgen(
this, 2);
7783 terminatetetgen(
this, 3);
7820 void tetgenmesh::flip23(triface* fliptets,
int hullflag, flipconstraints *fc)
7822 triface topcastets[3], botcastets[3];
7823 triface newface, casface;
7824 point pa, pb, pc, pd, pe;
7825 REAL attrib, volume;
7831 if (oppo(fliptets[1]) == dummypoint) {
7833 newface = fliptets[0];
7834 fliptets[0] = fliptets[1];
7835 fliptets[1] = newface;
7839 if (org(fliptets[0]) == dummypoint) {
7841 enextself(fliptets[0]);
7842 eprevself(fliptets[1]);
7843 }
else if (dest(fliptets[0]) == dummypoint) {
7845 eprevself(fliptets[0]);
7846 enextself(fliptets[1]);
7853 pa = org(fliptets[0]);
7854 pb = dest(fliptets[0]);
7855 pc = apex(fliptets[0]);
7856 pd = oppo(fliptets[0]);
7857 pe = oppo(fliptets[1]);
7862 for (i = 0; i < 3; i++) {
7863 fnext(fliptets[0], topcastets[i]);
7864 enextself(fliptets[0]);
7866 for (i = 0; i < 3; i++) {
7867 fnext(fliptets[1], botcastets[i]);
7868 eprevself(fliptets[1]);
7872 fliptets[0].ver = 11;
7873 fliptets[1].ver = 11;
7874 setelemmarker(fliptets[0].tet, 0);
7875 setelemmarker(fliptets[1].tet, 0);
7877 if (checksubsegflag) {
7879 if (fliptets[0].tet[8] != NULL) {
7880 tet2segpool->dealloc((shellface *) fliptets[0].tet[8]);
7881 fliptets[0].tet[8] = NULL;
7883 if (fliptets[1].tet[8] != NULL) {
7884 tet2segpool->dealloc((shellface *) fliptets[1].tet[8]);
7885 fliptets[1].tet[8] = NULL;
7888 if (checksubfaceflag) {
7890 if (fliptets[0].tet[9] != NULL) {
7891 tet2subpool->dealloc((shellface *) fliptets[0].tet[9]);
7892 fliptets[0].tet[9] = NULL;
7894 if (fliptets[1].tet[9] != NULL) {
7895 tet2subpool->dealloc((shellface *) fliptets[1].tet[9]);
7896 fliptets[1].tet[9] = NULL;
7900 maketetrahedron(&(fliptets[2]));
7902 for (i = 0; i < numelemattrib; i++) {
7903 attrib = elemattribute(fliptets[0].tet, i);
7904 setelemattribute(fliptets[2].tet, i, attrib);
7907 volume = volumebound(fliptets[0].tet);
7908 setvolumebound(fliptets[2].tet, volume);
7913 if (pd != dummypoint) {
7914 setvertices(fliptets[0], pe, pd, pa, pb);
7915 setvertices(fliptets[1], pe, pd, pb, pc);
7917 if (pc != dummypoint) {
7918 setvertices(fliptets[2], pe, pd, pc, pa);
7920 setvertices(fliptets[2], pd, pe, pa, pc);
7921 esymself(fliptets[2]);
7926 setvertices(fliptets[0], pa, pb, pe, pd);
7927 setvertices(fliptets[1], pb, pc, pe, pd);
7928 setvertices(fliptets[2], pc, pa, pe, pd);
7930 for (i = 0; i < 3; i++) {
7931 eprevesymself(fliptets[i]);
7932 enextself(fliptets[i]);
7938 setvertices(fliptets[0], pe, pd, pa, pb);
7939 setvertices(fliptets[1], pe, pd, pb, pc);
7940 setvertices(fliptets[2], pe, pd, pc, pa);
7943 if (fc->remove_ndelaunay_edge) {
7944 REAL volneg[2], volpos[3], vol_diff;
7945 if (pd != dummypoint) {
7946 if (pc != dummypoint) {
7947 volpos[0] = tetprismvol(pe, pd, pa, pb);
7948 volpos[1] = tetprismvol(pe, pd, pb, pc);
7949 volpos[2] = tetprismvol(pe, pd, pc, pa);
7950 volneg[0] = tetprismvol(pa, pb, pc, pd);
7951 volneg[1] = tetprismvol(pb, pa, pc, pe);
7953 volpos[0] = tetprismvol(pe, pd, pa, pb);
7964 volneg[1] = tetprismvol(pb, pa, pc, pe);
7966 vol_diff = volpos[0] + volpos[1] + volpos[2] - volneg[0] - volneg[1];
7967 fc->tetprism_vol_sum += vol_diff;
7971 for (i = 0; i < 3; i++) {
7972 esym(fliptets[i], newface);
7973 bond(newface, fliptets[(i + 1) % 3]);
7976 for (i = 0; i < 3; i++) {
7977 eorgoppo(fliptets[i], newface);
7978 bond(newface, topcastets[i]);
7981 for (i = 0; i < 3; i++) {
7982 edestoppo(fliptets[i], newface);
7983 bond(newface, botcastets[i]);
7986 if (checksubsegflag) {
7991 for (i = 0; i < 3; i++) {
7992 if (issubseg(topcastets[i])) {
7993 tsspivot1(topcastets[i], checkseg);
7994 eorgoppo(fliptets[i], newface);
7995 tssbond1(newface, checkseg);
7996 sstbond1(checkseg, newface);
7997 if (fc->chkencflag & 1) {
7998 enqueuesubface(badsubsegs, &checkseg);
8003 for (i = 0; i < 3; i++) {
8004 eprev(topcastets[i], casface);
8005 if (issubseg(casface)) {
8006 tsspivot1(casface, checkseg);
8007 enext(fliptets[i], newface);
8008 tssbond1(newface, checkseg);
8009 sstbond1(checkseg, newface);
8010 esym(fliptets[(i + 2) % 3], newface);
8012 tssbond1(newface, checkseg);
8013 sstbond1(checkseg, newface);
8014 if (fc->chkencflag & 1) {
8015 enqueuesubface(badsubsegs, &checkseg);
8020 for (i = 0; i < 3; i++) {
8021 enext(botcastets[i], casface);
8022 if (issubseg(casface)) {
8023 tsspivot1(casface, checkseg);
8024 eprev(fliptets[i], newface);
8025 tssbond1(newface, checkseg);
8026 sstbond1(checkseg, newface);
8027 esym(fliptets[(i + 2) % 3], newface);
8029 tssbond1(newface, checkseg);
8030 sstbond1(checkseg, newface);
8031 if (fc->chkencflag & 1) {
8032 enqueuesubface(badsubsegs, &checkseg);
8038 if (checksubfaceflag) {
8041 for (i = 0; i < 3; i++) {
8042 if (issubface(topcastets[i])) {
8043 tspivot(topcastets[i], checksh);
8044 eorgoppo(fliptets[i], newface);
8046 tsbond(newface, checksh);
8047 if (fc->chkencflag & 2) {
8048 enqueuesubface(badsubfacs, &checksh);
8052 for (i = 0; i < 3; i++) {
8053 if (issubface(botcastets[i])) {
8054 tspivot(botcastets[i], checksh);
8055 edestoppo(fliptets[i], newface);
8057 tsbond(newface, checksh);
8058 if (fc->chkencflag & 2) {
8059 enqueuesubface(badsubfacs, &checksh);
8065 if (fc->chkencflag & 4) {
8067 for (i = 0; i < 3; i++) {
8068 enqueuetetrahedron(&(fliptets[i]));
8073 setpoint2tet(pa, (tetrahedron) fliptets[0].tet);
8074 setpoint2tet(pb, (tetrahedron) fliptets[0].tet);
8075 setpoint2tet(pc, (tetrahedron) fliptets[1].tet);
8076 setpoint2tet(pd, (tetrahedron) fliptets[0].tet);
8077 setpoint2tet(pe, (tetrahedron) fliptets[0].tet);
8080 if (dummyflag != 0) {
8082 if (dummyflag == -1) {
8084 for (i = 0; i < 3; i++) {
8085 esymself(fliptets[i]);
8088 newface = fliptets[1];
8089 fliptets[1] = fliptets[2];
8090 fliptets[2] = newface;
8093 if (dummyflag == 1) {
8095 newface = fliptets[0];
8096 fliptets[0] = fliptets[2];
8097 fliptets[2] = fliptets[1];
8098 fliptets[1] = newface;
8101 newface = fliptets[0];
8102 fliptets[0] = fliptets[1];
8103 fliptets[1] = fliptets[2];
8104 fliptets[2] = newface;
8110 if (fc->enqflag > 0) {
8112 for (i = 0; i < 3; i++) {
8113 eprevesym(fliptets[i], newface);
8114 flippush(flipstack, &newface);
8116 if (fc->enqflag > 1) {
8117 for (i = 0; i < 3; i++) {
8118 enextesym(fliptets[i], newface);
8119 flippush(flipstack, &newface);
8124 recenttet = fliptets[0];
8159 void tetgenmesh::flip32(triface* fliptets,
int hullflag, flipconstraints *fc)
8161 triface topcastets[3], botcastets[3];
8162 triface newface, casface;
8165 point pa, pb, pc, pd, pe;
8166 REAL attrib, volume;
8168 int spivot = -1, scount = 0;
8174 if (org(fliptets[0]) == dummypoint) {
8176 for (i = 0; i < 3; i++) {
8177 esymself(fliptets[i]);
8180 newface = fliptets[1];
8181 fliptets[1] = fliptets[2];
8182 fliptets[2] = newface;
8186 if (apex(fliptets[0]) == dummypoint) {
8188 newface = fliptets[0];
8189 fliptets[0] = fliptets[1];
8190 fliptets[1] = fliptets[2];
8191 fliptets[2] = newface;
8192 }
else if (apex(fliptets[1]) == dummypoint) {
8194 newface = fliptets[0];
8195 fliptets[0] = fliptets[2];
8196 fliptets[2] = fliptets[1];
8197 fliptets[1] = newface;
8204 pa = apex(fliptets[0]);
8205 pb = apex(fliptets[1]);
8206 pc = apex(fliptets[2]);
8207 pd = dest(fliptets[0]);
8208 pe = org(fliptets[0]);
8213 for (i = 0; i < 3; i++) {
8214 eorgoppo(fliptets[i], casface);
8215 fsym(casface, topcastets[i]);
8217 for (i = 0; i < 3; i++) {
8218 edestoppo(fliptets[i], casface);
8219 fsym(casface, botcastets[i]);
8222 if (checksubfaceflag) {
8224 for (i = 0; i < 3; i++) {
8225 tspivot(fliptets[i], flipshs[i]);
8226 if (flipshs[i].sh != NULL) {
8228 stdissolve(flipshs[i]);
8237 fliptets[0].ver = 11;
8238 fliptets[1].ver = 11;
8239 setelemmarker(fliptets[0].tet, 0);
8240 setelemmarker(fliptets[1].tet, 0);
8241 if (checksubsegflag) {
8243 if (fliptets[0].tet[8] != NULL) {
8244 tet2segpool->dealloc((shellface *) fliptets[0].tet[8]);
8245 fliptets[0].tet[8] = NULL;
8247 if (fliptets[1].tet[8] != NULL) {
8248 tet2segpool->dealloc((shellface *) fliptets[1].tet[8]);
8249 fliptets[1].tet[8] = NULL;
8252 if (checksubfaceflag) {
8254 if (fliptets[0].tet[9] != NULL) {
8255 tet2subpool->dealloc((shellface *) fliptets[0].tet[9]);
8256 fliptets[0].tet[9] = NULL;
8258 if (fliptets[1].tet[9] != NULL) {
8259 tet2subpool->dealloc((shellface *) fliptets[1].tet[9]);
8260 fliptets[1].tet[9] = NULL;
8263 if (checksubfaceflag) {
8273 for (j = 0; j < 2; j++) {
8274 for (i = 0; i < numelemattrib; i++) {
8275 attrib = elemattribute(fliptets[spivot].tet, i);
8276 setelemattribute(fliptets[j].tet, i, attrib);
8279 volume = volumebound(fliptets[spivot].tet);
8280 setvolumebound(fliptets[j].tet, volume);
8286 tetrahedrondealloc(fliptets[2].tet);
8290 if (pc != dummypoint) {
8292 if (pd != dummypoint) {
8298 setvertices(fliptets[0], pa, pb, pc, pd);
8299 setvertices(fliptets[1], pb, pa, pc, pe);
8302 setvertices(fliptets[0], pb, pa, pd, pc);
8303 setvertices(fliptets[1], pa, pb, pe, pc);
8305 esymself(fliptets[0]);
8307 esymself(fliptets[1]);
8311 setvertices(fliptets[0], pa, pb, pc, pd);
8312 setvertices(fliptets[1], pb, pa, pc, pe);
8315 if (fc->remove_ndelaunay_edge) {
8316 REAL volneg[3], volpos[2], vol_diff;
8317 if (pc != dummypoint) {
8318 if (pd != dummypoint) {
8319 volneg[0] = tetprismvol(pe, pd, pa, pb);
8320 volneg[1] = tetprismvol(pe, pd, pb, pc);
8321 volneg[2] = tetprismvol(pe, pd, pc, pa);
8322 volpos[0] = tetprismvol(pa, pb, pc, pd);
8323 volpos[1] = tetprismvol(pb, pa, pc, pe);
8329 volpos[1] = tetprismvol(pb, pa, pc, pe);
8332 volneg[0] = tetprismvol(pe, pd, pa, pb);
8338 vol_diff = volpos[0] + volpos[1] - volneg[0] - volneg[1] - volneg[2];
8339 fc->tetprism_vol_sum += vol_diff;
8343 bond(fliptets[0], fliptets[1]);
8345 for (i = 0; i < 3; i++) {
8346 esym(fliptets[0], newface);
8347 bond(newface, topcastets[i]);
8348 enextself(fliptets[0]);
8351 for (i = 0; i < 3; i++) {
8352 esym(fliptets[1], newface);
8353 bond(newface, botcastets[i]);
8354 eprevself(fliptets[1]);
8357 if (checksubsegflag) {
8359 for (i = 0; i < 3; i++) {
8360 if (issubseg(topcastets[i])) {
8361 tsspivot1(topcastets[i], checkseg);
8362 tssbond1(fliptets[0], checkseg);
8363 sstbond1(checkseg, fliptets[0]);
8364 tssbond1(fliptets[1], checkseg);
8365 sstbond1(checkseg, fliptets[1]);
8366 if (fc->chkencflag & 1) {
8367 enqueuesubface(badsubsegs, &checkseg);
8370 enextself(fliptets[0]);
8371 eprevself(fliptets[1]);
8374 for (i = 0; i < 3; i++) {
8375 esym(fliptets[0], newface);
8377 enext(topcastets[i], casface);
8378 if (issubseg(casface)) {
8379 tsspivot1(casface, checkseg);
8380 tssbond1(newface, checkseg);
8381 sstbond1(checkseg, newface);
8382 if (fc->chkencflag & 1) {
8383 enqueuesubface(badsubsegs, &checkseg);
8386 enextself(fliptets[0]);
8389 for (i = 0; i < 3; i++) {
8390 esym(fliptets[1], newface);
8392 eprev(botcastets[i], casface);
8393 if (issubseg(casface)) {
8394 tsspivot1(casface, checkseg);
8395 tssbond1(newface, checkseg);
8396 sstbond1(checkseg, newface);
8397 if (fc->chkencflag & 1) {
8398 enqueuesubface(badsubsegs, &checkseg);
8401 eprevself(fliptets[1]);
8405 if (checksubfaceflag) {
8408 for (i = 0; i < 3; i++) {
8409 if (issubface(topcastets[i])) {
8410 tspivot(topcastets[i], checksh);
8411 esym(fliptets[0], newface);
8413 tsbond(newface, checksh);
8414 if (fc->chkencflag & 2) {
8415 enqueuesubface(badsubfacs, &checksh);
8418 enextself(fliptets[0]);
8421 for (i = 0; i < 3; i++) {
8422 if (issubface(botcastets[i])) {
8423 tspivot(botcastets[i], checksh);
8424 esym(fliptets[1], newface);
8426 tsbond(newface, checksh);
8427 if (fc->chkencflag & 2) {
8428 enqueuesubface(badsubfacs, &checksh);
8431 eprevself(fliptets[1]);
8437 flipfaces[0] = flipshs[(spivot + 1) % 3];
8438 flipfaces[1] = flipshs[(spivot + 2) % 3];
8439 sesymself(flipfaces[1]);
8440 flip22(flipfaces, 0, fc->chkencflag);
8444 topcastets[0] = fliptets[0];
8445 botcastets[0] = fliptets[1];
8446 for (i = 0; i < ((spivot + 1) % 3); i++) {
8447 enextself(topcastets[0]);
8448 eprevself(botcastets[0]);
8451 esymself(topcastets[0]);
8452 sesymself(flipfaces[0]);
8454 tspivot(topcastets[0], checksh);
8455 if (checksh.sh == NULL) {
8456 tsbond(topcastets[0], flipfaces[0]);
8457 fsymself(topcastets[0]);
8458 sesymself(flipfaces[0]);
8459 tsbond(topcastets[0], flipfaces[0]);
8462 terminatetetgen(
this, 2);
8465 esymself(botcastets[0]);
8466 sesymself(flipfaces[1]);
8468 tspivot(botcastets[0], checksh);
8469 if (checksh.sh == NULL) {
8470 tsbond(botcastets[0], flipfaces[1]);
8471 fsymself(botcastets[0]);
8472 sesymself(flipfaces[1]);
8473 tsbond(botcastets[0], flipfaces[1]);
8476 terminatetetgen(
this, 2);
8481 if (fc->chkencflag & 4) {
8483 for (i = 0; i < 2; i++) {
8484 enqueuetetrahedron(&(fliptets[i]));
8488 setpoint2tet(pa, (tetrahedron) fliptets[0].tet);
8489 setpoint2tet(pb, (tetrahedron) fliptets[0].tet);
8490 setpoint2tet(pc, (tetrahedron) fliptets[0].tet);
8491 setpoint2tet(pd, (tetrahedron) fliptets[0].tet);
8492 setpoint2tet(pe, (tetrahedron) fliptets[1].tet);
8495 if (dummyflag != 0) {
8497 if (dummyflag == -1) {
8499 newface = fliptets[0];
8500 fliptets[0] = fliptets[1];
8501 fliptets[1] = newface;
8504 if (dummyflag == 1) {
8505 eprevself(fliptets[0]);
8506 enextself(fliptets[1]);
8508 enextself(fliptets[0]);
8509 eprevself(fliptets[1]);
8515 if (fc->enqflag > 0) {
8518 enextesym(fliptets[0], newface);
8519 flippush(flipstack, &newface);
8520 eprevesym(fliptets[1], newface);
8521 flippush(flipstack, &newface);
8522 if (fc->enqflag > 1) {
8524 eprevesym(fliptets[0], newface);
8525 flippush(flipstack, &newface);
8526 enextesym(fliptets[1], newface);
8527 flippush(flipstack, &newface);
8529 esym(fliptets[0], newface);
8530 flippush(flipstack, &newface);
8531 esym(fliptets[1], newface);
8532 flippush(flipstack, &newface);
8536 recenttet = fliptets[0];
8561 void tetgenmesh::flip41(triface* fliptets,
int hullflag, flipconstraints *fc)
8563 triface topcastets[3], botcastet;
8564 triface newface, neightet;
8566 point pa, pb, pc, pd, pp;
8568 int spivot = -1, scount = 0;
8572 pa = org(fliptets[3]);
8573 pb = dest(fliptets[3]);
8574 pc = apex(fliptets[3]);
8575 pd = dest(fliptets[0]);
8576 pp = org(fliptets[0]);
8581 for (i = 0; i < 3; i++) {
8582 enext(fliptets[i], topcastets[i]);
8583 fnextself(topcastets[i]);
8584 enextself(topcastets[i]);
8586 fsym(fliptets[3], botcastet);
8588 if (checksubfaceflag) {
8591 for (i = 0; i < 3; i++) {
8592 fnext(fliptets[3], newface);
8593 tspivot(newface, flipshs[i]);
8594 if (flipshs[i].sh != NULL) {
8598 enextself(fliptets[3]);
8605 fsym(topcastets[spivot], neightet);
8607 for (i = 0; i < 3; i++) {
8608 esym(neightet, newface);
8609 tspivot(newface, flipshs[i]);
8610 eprevself(neightet);
8620 fliptets[0].ver = 11;
8621 setelemmarker(fliptets[0].tet, 0);
8623 if (checksubsegflag) {
8625 if (fliptets[0].tet[8] != NULL) {
8626 tet2segpool->dealloc((shellface *) fliptets[0].tet[8]);
8627 fliptets[0].tet[8] = NULL;
8630 if (checksubfaceflag) {
8632 if (fliptets[0].tet[9] != NULL) {
8633 tet2subpool->dealloc((shellface *) fliptets[0].tet[9]);
8634 fliptets[0].tet[9] = NULL;
8638 for (i = 1; i < 4; i++) {
8639 tetrahedrondealloc(fliptets[i].tet);
8642 if (pp != dummypoint) {
8644 setpointtype(pp, UNUSEDVERTEX);
8651 if (pa == dummypoint) {
8653 setvertices(fliptets[0], pc, pb, pd, pa);
8654 esymself(fliptets[0]);
8655 eprevself(fliptets[0]);
8657 }
else if (pb == dummypoint) {
8658 setvertices(fliptets[0], pa, pc, pd, pb);
8659 esymself(fliptets[0]);
8660 enextself(fliptets[0]);
8662 }
else if (pc == dummypoint) {
8663 setvertices(fliptets[0], pb, pa, pd, pc);
8664 esymself(fliptets[0]);
8666 }
else if (pd == dummypoint) {
8667 setvertices(fliptets[0], pa, pb, pc, pd);
8670 setvertices(fliptets[0], pa, pb, pc, pd);
8671 if (pp == dummypoint) {
8677 if (dummyflag > 0) {
8680 }
else if (dummyflag < 0) {
8686 setvertices(fliptets[0], pa, pb, pc, pd);
8689 if (fc->remove_ndelaunay_edge) {
8690 REAL volneg[4], volpos[1], vol_diff;
8691 if (dummyflag > 0) {
8692 if (pa == dummypoint) {
8694 volneg[1] = tetprismvol(pp, pd, pb, pc);
8697 }
else if (pb == dummypoint) {
8700 volneg[2] = tetprismvol(pp, pd, pc, pa);
8702 }
else if (pc == dummypoint) {
8703 volneg[0] = tetprismvol(pp, pd, pa, pb);
8711 volneg[3] = tetprismvol(pa, pb, pc, pp);
8714 }
else if (dummyflag < 0) {
8719 volpos[0] = tetprismvol(pa, pb, pc, pd);
8721 volneg[0] = tetprismvol(pp, pd, pa, pb);
8722 volneg[1] = tetprismvol(pp, pd, pb, pc);
8723 volneg[2] = tetprismvol(pp, pd, pc, pa);
8724 volneg[3] = tetprismvol(pa, pb, pc, pp);
8725 volpos[0] = tetprismvol(pa, pb, pc, pd);
8727 vol_diff = volpos[0] - volneg[0] - volneg[1] - volneg[2] - volneg[3];
8728 fc->tetprism_vol_sum += vol_diff;
8732 for (i = 0; i < 3; i++) {
8733 esym(fliptets[0], newface);
8734 bond(newface, topcastets[i]);
8735 enextself(fliptets[0]);
8737 bond(fliptets[0], botcastet);
8739 if (checksubsegflag) {
8742 for (i = 0; i < 3; i++) {
8743 eprev(topcastets[i], newface);
8744 if (issubseg(newface)) {
8745 tsspivot1(newface, checkseg);
8746 esym(fliptets[0], newface);
8748 tssbond1(newface, checkseg);
8749 sstbond1(checkseg, newface);
8750 if (fc->chkencflag & 1) {
8751 enqueuesubface(badsubsegs, &checkseg);
8754 enextself(fliptets[0]);
8756 for (i = 0; i < 3; i++) {
8757 if (issubseg(topcastets[i])) {
8758 tsspivot1(topcastets[i], checkseg);
8759 tssbond1(fliptets[0], checkseg);
8760 sstbond1(checkseg, fliptets[0]);
8761 if (fc->chkencflag & 1) {
8762 enqueuesubface(badsubsegs, &checkseg);
8765 enextself(fliptets[0]);
8769 if (checksubfaceflag) {
8772 for (i = 0; i < 3; i++) {
8773 if (issubface(topcastets[i])) {
8774 tspivot(topcastets[i], checksh);
8775 esym(fliptets[0], newface);
8777 tsbond(newface, checksh);
8778 if (fc->chkencflag & 2) {
8779 enqueuesubface(badsubfacs, &checksh);
8782 enextself(fliptets[0]);
8784 if (issubface(botcastet)) {
8785 tspivot(botcastet, checksh);
8787 tsbond(fliptets[0], checksh);
8788 if (fc->chkencflag & 2) {
8789 enqueuesubface(badsubfacs, &checksh);
8802 for (i = 0; i < 3; i++) {
8803 senext2self(flipshs[i]);
8807 for (i = 0; i < 3; i++) {
8808 shellfacedealloc(subfaces, flipshs[i].sh);
8812 tsbond(topcastets[spivot], flipshs[3]);
8813 fsym(topcastets[spivot], newface);
8814 sesym(flipshs[3], checksh);
8815 tsbond(newface, checksh);
8818 tsbond(fliptets[0], flipshs[3]);
8819 fsym(fliptets[0], newface);
8820 sesym(flipshs[3], checksh);
8821 tsbond(newface, checksh);
8826 if (fc->chkencflag & 4) {
8827 enqueuetetrahedron(&(fliptets[0]));
8831 setpoint2tet(pa, (tetrahedron) fliptets[0].tet);
8832 setpoint2tet(pb, (tetrahedron) fliptets[0].tet);
8833 setpoint2tet(pc, (tetrahedron) fliptets[0].tet);
8834 setpoint2tet(pd, (tetrahedron) fliptets[0].tet);
8836 if (fc->enqflag > 0) {
8838 flippush(flipstack, &(fliptets[0]));
8839 if (fc->enqflag > 1) {
8840 for (i = 0; i < 3; i++) {
8841 esym(fliptets[0], newface);
8842 flippush(flipstack, &newface);
8843 enextself(fliptets[0]);
8848 recenttet = fliptets[0];
8880 int tetgenmesh::flipnm(triface* abtets,
int n,
int level,
int abedgepivot,
8881 flipconstraints* fc)
8883 triface fliptets[3], spintet, flipedge;
8884 triface *tmpabtets, *parytet;
8885 point pa, pb, pc, pd, pe, pf;
8887 int hullflag, hulledgeflag;
8888 int reducflag, rejflag;
8889 int reflexlinkedgecount;
8895 pa = org(abtets[0]);
8896 pb = dest(abtets[0]);
8900 reflexlinkedgecount = 0;
8902 for (i = 0; i < n; i++) {
8904 if (checksubfaceflag) {
8905 if (issubface(abtets[i])) {
8910 if ((elemcounter(abtets[i]) > 1) ||
8911 (elemcounter(abtets[(i - 1 + n) % n]) > 1)) {
8915 pc = apex(abtets[i]);
8916 pd = apex(abtets[(i + 1) % n]);
8917 pe = apex(abtets[(i - 1 + n) % n]);
8918 if ((pd == dummypoint) || (pe == dummypoint)) {
8926 hullflag = (pc == dummypoint);
8928 if (hullflag == 0) {
8929 ori = orient3d(pb, pc, pd, pe);
8931 ori = orient3d(pc, pa, pd, pe);
8934 ori = orient3d(pa, pb, pd, pe);
8938 }
else if (ori == 0) {
8944 pf = apex(abtets[(i + 2) % n]);
8945 hulledgeflag = (pf == dummypoint);
8951 reflexlinkedgecount++;
8962 pf = apex(abtets[(i + 2) % n]);
8963 ori = orient3d(pd, pe, pf, pa);
8965 ori = orient3d(pe, pd, pf, pb);
8977 if (nonconvex && hulledgeflag) {
8979 if (getedge(pe, pd, &spintet)) {
8989 if (fc->checkflipeligibility) {
8991 rejflag = checkflipeligibility(1, pa, pb, pc, pd, pe, level,
8996 fliptets[0] = abtets[i];
8997 fsym(fliptets[0], fliptets[1]);
8998 flip23(fliptets, hullflag, fc);
9016 edestoppoself(fliptets[0]);
9018 increaseelemcounter(fliptets[0]);
9019 abtets[(i - 1 + n) % n] = fliptets[0];
9020 for (j = i; j < n - 1; j++) {
9021 abtets[j] = abtets[j + 1];
9028 abtets[n - 1].tet = (tetrahedron *) pc;
9029 abtets[n - 1].ver = 0;
9032 abtets[n - 1].ver |= (1 << 4);
9034 abtets[n - 1].ver |= (i << 6);
9036 if (fc->collectnewtets) {
9039 for (j = 1; j < 3; j++) {
9040 cavetetlist->newindex((
void **) &parytet);
9041 *parytet = fliptets[j];
9046 nn = flipnm(abtets, n - 1, level, abedgepivot, fc);
9053 if (fc->unflip || (ori == 0)) {
9060 fliptets[0] = abtets[(i-1 + (n-1)) % (n-1)];
9061 edestoppoself(fliptets[0]);
9062 fnext(fliptets[0], fliptets[1]);
9063 fnext(fliptets[1], fliptets[2]);
9065 flip32(fliptets, hullflag, fc);
9067 for (j = 0; j < 2; j++) {
9068 increaseelemcounter(fliptets[j]);
9071 for (j = n - 2; j>= i; j--) {
9072 abtets[j + 1] = abtets[j];
9077 esym(fliptets[1], abtets[(i - 1 + n) % n]);
9078 abtets[i] = fliptets[0];
9080 if (fc->collectnewtets) {
9082 cavetetlist->objects -= 2;
9099 if (reflexlinkedgecount > 0) {
9101 if (((b->fliplinklevel < 0) && (level < autofliplinklevel)) ||
9102 ((b->fliplinklevel >= 0) && (level < b->fliplinklevel))) {
9104 for (i = 0; i < n; i++) {
9106 if ((elemcounter(abtets[i]) > 1) ||
9107 (elemcounter(abtets[(i - 1 + n) % n]) > 1)) {
9110 pc = apex(abtets[i]);
9111 if (pc == dummypoint) {
9114 pd = apex(abtets[(i + 1) % n]);
9115 pe = apex(abtets[(i - 1 + n) % n]);
9116 if ((pd == dummypoint) || (pe == dummypoint)) {
9124 ori = orient3d(pb, pc, pd, pe);
9127 enext(abtets[i], flipedge);
9132 ori = orient3d(pc, pa, pd, pe);
9135 eprev(abtets[i], flipedge);
9140 if (!edgepivot)
continue;
9143 if (checksubsegflag) {
9145 if (issubseg(flipedge)) {
9146 if (fc->collectencsegflag) {
9147 face checkseg, *paryseg;
9148 tsspivot1(flipedge, checkseg);
9149 if (!sinfected(checkseg)) {
9152 caveencseglist->newindex((
void **) &paryseg);
9153 *paryseg = checkseg;
9168 j += (elemcounter(spintet));
9170 if (spintet.tet == flipedge.tet)
break;
9175 terminatetetgen(
this, 2);
9182 if ((b->flipstarsize > 0) && (n1 > b->flipstarsize)) {
9188 tmpabtets =
new triface[n1];
9193 tmpabtets[j] = spintet;
9195 increaseelemcounter(tmpabtets[j]);
9198 if (spintet.tet == flipedge.tet)
break;
9202 nn = flipnm(tmpabtets, n1, level + 1, edgepivot, fc);
9207 if (edgepivot == 1) {
9209 spintet = tmpabtets[0];
9215 spintet = tmpabtets[1];
9220 increaseelemcounter(spintet);
9222 abtets[(i - 1 + n) % n] = spintet;
9223 for (j = i; j < n - 1; j++) {
9224 abtets[j] = abtets[j + 1];
9228 abtets[n - 1].tet = (tetrahedron *) tmpabtets;
9229 abtets[n - 1].ver = 0;
9231 abtets[n - 1].ver |= edgepivot;
9233 abtets[n - 1].ver |= (1 << 5);
9235 abtets[n - 1].ver |= (i << 6);
9237 abtets[n - 1].ver |= (n1 << 19);
9241 tmpabtets[0].tet = (tetrahedron *) pc;
9242 tmpabtets[0].ver = (1 << 5);
9245 nn = flipnm(abtets, n - 1, level, abedgepivot, fc);
9258 if (edgepivot == 1) {
9260 tmpabtets[0] = abtets[((i-1)+(n-1))%(n-1)];
9261 eprevself(tmpabtets[0]);
9262 esymself(tmpabtets[0]);
9263 eprevself(tmpabtets[0]);
9264 fsym(tmpabtets[0], tmpabtets[1]);
9267 tmpabtets[1] = abtets[((i-1)+(n-1))%(n-1)];
9268 enextself(tmpabtets[1]);
9269 esymself(tmpabtets[1]);
9270 enextself(tmpabtets[1]);
9271 fsym(tmpabtets[1], tmpabtets[0]);
9275 flipnm_post(tmpabtets, n1, 2, edgepivot, fc);
9278 for (j = n - 2; j >= i; j--) {
9279 abtets[j + 1] = abtets[j];
9281 if (edgepivot == 1) {
9285 fliptets[0] = tmpabtets[1];
9286 enextself(fliptets[0]);
9287 esymself(fliptets[0]);
9288 fliptets[1] = tmpabtets[0];
9289 esymself(fliptets[1]);
9290 eprevself(fliptets[1]);
9295 fliptets[0] = tmpabtets[1];
9296 eprevself(fliptets[0]);
9297 esymself(fliptets[0]);
9298 fliptets[1] = tmpabtets[0];
9299 esymself(fliptets[1]);
9300 enextself(fliptets[1]);
9302 for (j = 0; j < 2; j++) {
9303 increaseelemcounter(fliptets[j]);
9306 abtets[(i - 1 + n) % n] = fliptets[0];
9307 abtets[i] = fliptets[1];
9310 delete [] tmpabtets;
9325 flipnm_post(tmpabtets, n1, nn, edgepivot, fc);
9328 for (j = 0; j < nn; j++) {
9329 decreaseelemcounter(tmpabtets[j]);
9332 delete [] tmpabtets;
9343 if (apex(abtets[0]) == dummypoint) {
9344 pc = apex(abtets[1]);
9345 pd = apex(abtets[2]);
9346 pe = apex(abtets[0]);
9348 }
else if (apex(abtets[1]) == dummypoint) {
9349 pc = apex(abtets[2]);
9350 pd = apex(abtets[0]);
9351 pe = apex(abtets[1]);
9354 pc = apex(abtets[0]);
9355 pd = apex(abtets[1]);
9356 pe = apex(abtets[2]);
9357 hullflag = (pe == dummypoint) ? 3 : 0;
9364 if (hullflag == 0) {
9367 ori = orient3d(pd, pc, pe, pa);
9369 ori = orient3d(pc, pd, pe, pb);
9380 ori = orient3d(pa, pb, pc, pd);
9387 if (reducflag == 1) {
9390 point searchpt = NULL, chkpt;
9391 REAL bigvol = 0.0, ori1, ori2;
9396 fliptets[0] = abtets[hullflag % 3];
9397 eorgoppoself(fliptets[0]);
9398 spintet = fliptets[0];
9401 chkpt = oppo(spintet);
9402 if (chkpt == pb)
break;
9403 if ((chkpt != dummypoint) && (apex(spintet) != dummypoint)) {
9404 ori = -orient3d(pd, pc, apex(spintet), chkpt);
9411 if (searchpt != NULL) {
9413 ori1 = orient3d(pd, pc, searchpt, pa);
9414 ori2 = orient3d(pd, pc, searchpt, pb);
9415 if (ori1 * ori2 >= 0.0) {
9418 ori1 = orient3d(pa, pb, searchpt, pc);
9419 ori2 = orient3d(pa, pb, searchpt, pd);
9420 if (ori1 * ori2 >= 0.0) {
9433 if (checksubfaceflag) {
9440 for (j = 0; j < 3; j++) {
9441 if (issubface(abtets[j])) {
9452 }
else if (nn == 2) {
9455 eorgoppo(abtets[(edgepivot + 1) % 3], spintet);
9456 if (issubface(spintet)) {
9460 if (issubface(spintet)) {
9464 }
else if (nn == 3) {
9466 terminatetetgen(
this, 2);
9469 if (!rejflag && fc->checkflipeligibility) {
9474 rejflag = checkflipeligibility(2, pc, pd, pe, pb, pa, level,
9479 flip32(abtets, hullflag, fc);
9480 if (fc->remove_ndelaunay_edge) {
9484 if ((fc->tetprism_vol_sum >= 0.0) ||
9485 (fabs(fc->tetprism_vol_sum) < fc->bak_tetprism_vol)) {
9487 flip23(abtets, hullflag, fc);
9489 for (j = 0; j < 3; j++) {
9490 increaseelemcounter(abtets[j]);
9496 if (fc->collectnewtets) {
9500 for (j = 0; j < 2; j++) {
9501 cavetetlist->newindex((
void **) &parytet);
9502 *parytet = abtets[j];
9507 cavetetlist->newindex((
void **) &parytet);
9508 if (abedgepivot == 1) {
9509 *parytet = abtets[1];
9511 *parytet = abtets[0];
9554 int tetgenmesh::flipnm_post(triface* abtets,
int n,
int nn,
int abedgepivot,
9555 flipconstraints* fc)
9557 triface fliptets[3], flipface;
9571 flip23(abtets, 1, fc);
9572 if (fc->collectnewtets) {
9574 if (abedgepivot == 0) {
9576 cavetetlist->objects -= 2;
9579 cavetetlist->objects -= 1;
9588 for (i = nn; i < n; i++) {
9592 fliptype = ((abtets[i].ver >> 4) & 3);
9593 if (fliptype == 1) {
9595 t = (abtets[i].ver >> 6);
9597 if (b->verbose > 2) {
9598 printf(
" Recover a 2-to-3 flip at f[%d].\n", t);
9602 fliptets[0] = abtets[((t - 1) + i) % i];
9603 eprevself(fliptets[0]);
9604 esymself(fliptets[0]);
9605 enextself(fliptets[0]);
9606 fnext(fliptets[0], fliptets[1]);
9607 fnext(fliptets[1], fliptets[2]);
9610 flip32(fliptets, 1, fc);
9613 for (j = i - 1; j >= t; j--) {
9614 abtets[j + 1] = abtets[j];
9619 esym(fliptets[1], abtets[((t-1) + (i+1)) % (i+1)]);
9620 abtets[t] = fliptets[0];
9621 if (fc->collectnewtets) {
9623 cavetetlist->objects -= 2;
9626 }
else if (fliptype == 2) {
9627 tmpabtets = (triface *) (abtets[i].tet);
9628 n1 = ((abtets[i].ver >> 19) & 8191);
9629 edgepivot = (abtets[i].ver & 3);
9630 t = ((abtets[i].ver >> 6) & 8191);
9632 if (b->verbose > 2) {
9633 printf(
" Recover a %d-to-m flip at e[%d] of f[%d].\n", n1,
9640 if (edgepivot == 1) {
9642 tmpabtets[0] = abtets[(t - 1 + i) % i];
9643 eprevself(tmpabtets[0]);
9644 esymself(tmpabtets[0]);
9645 eprevself(tmpabtets[0]);
9646 fsym(tmpabtets[0], tmpabtets[1]);
9649 tmpabtets[1] = abtets[(t - 1 + i) % i];
9650 enextself(tmpabtets[1]);
9651 esymself(tmpabtets[1]);
9652 enextself(tmpabtets[1]);
9653 fsym(tmpabtets[1], tmpabtets[0]);
9657 flipnm_post(tmpabtets, n1, 2, edgepivot, fc);
9660 for (j = i - 1; j >= t; j--) {
9661 abtets[j + 1] = abtets[j];
9663 if (edgepivot == 1) {
9667 fliptets[0] = tmpabtets[1];
9668 enextself(fliptets[0]);
9669 esymself(fliptets[0]);
9670 fliptets[1] = tmpabtets[0];
9671 esymself(fliptets[1]);
9672 eprevself(fliptets[1]);
9677 fliptets[0] = tmpabtets[1];
9678 eprevself(fliptets[0]);
9679 esymself(fliptets[0]);
9680 fliptets[1] = tmpabtets[0];
9681 esymself(fliptets[1]);
9682 enextself(fliptets[1]);
9685 abtets[((t-1) + (i+1)) % (i+1)] = fliptets[0];
9686 abtets[t] = fliptets[1];
9690 flipnm_post(tmpabtets, n1, 2, edgepivot, fc);
9692 if (b->verbose > 2) {
9693 printf(
" Release %d spaces at f[%d].\n", n1, i);
9695 delete [] tmpabtets;
9717 int tetgenmesh::insertpoint(point insertpt, triface *searchtet, face *splitsh,
9718 face *splitseg, insertvertexflags *ivf)
9720 arraypool *swaplist;
9721 triface *cavetet, spintet, neightet, neineitet, *parytet;
9722 triface oldtet, newtet, newneitet;
9723 face checksh, neighsh, *parysh;
9724 face checkseg, *paryseg;
9725 point *pts, pa, pb, pc, *parypt;
9726 enum locateresult loc = OUTSIDE;
9728 REAL attrib, volume;
9733 if (b->verbose > 2) {
9734 printf(
" Insert point %d\n", pointmark(insertpt));
9738 if (searchtet->tet != NULL) {
9739 loc = (
enum locateresult) ivf->iloc;
9742 if (loc == OUTSIDE) {
9743 if (searchtet->tet == NULL) {
9745 randomsample(insertpt, searchtet);
9748 *searchtet = recenttet;
9752 loc = locate(insertpt, searchtet);
9755 ivf->iloc = (int) loc;
9758 if (loc != OUTSIDE) {
9760 pts = (point *) searchtet->tet;
9761 sign = orient4d_s(pts[4], pts[5], pts[6], pts[7], insertpt,
9762 pts[4][3], pts[5][3], pts[6][3], pts[7][3],
9766 ivf->iloc = (int) NONREGULAR;
9777 if (loc == OUTSIDE) {
9781 for (i = 0; i < 4; i++) {
9782 decode(searchtet->tet[i], neightet);
9783 neightet.ver = epivot[neightet.ver];
9784 cavebdrylist->newindex((
void **) &parytet);
9785 *parytet = neightet;
9788 caveoldtetlist->newindex((
void **) &parytet);
9789 *parytet = *searchtet;
9790 }
else if (loc == INTETRAHEDRON) {
9793 for (i = 0; i < 4; i++) {
9794 decode(searchtet->tet[i], neightet);
9795 neightet.ver = epivot[neightet.ver];
9796 cavebdrylist->newindex((
void **) &parytet);
9797 *parytet = neightet;
9800 caveoldtetlist->newindex((
void **) &parytet);
9801 *parytet = *searchtet;
9802 }
else if (loc == ONFACE) {
9805 j = (searchtet->ver & 3);
9806 for (i = 1; i < 4; i++) {
9807 decode(searchtet->tet[(j + i) % 4], neightet);
9808 neightet.ver = epivot[neightet.ver];
9809 cavebdrylist->newindex((
void **) &parytet);
9810 *parytet = neightet;
9812 decode(searchtet->tet[j], spintet);
9813 j = (spintet.ver & 3);
9814 for (i = 1; i < 4; i++) {
9815 decode(spintet.tet[(j + i) % 4], neightet);
9816 neightet.ver = epivot[neightet.ver];
9817 cavebdrylist->newindex((
void **) &parytet);
9818 *parytet = neightet;
9821 caveoldtetlist->newindex((
void **) &parytet);
9824 caveoldtetlist->newindex((
void **) &parytet);
9825 *parytet = *searchtet;
9827 if (ivf->splitbdflag) {
9828 if ((splitsh != NULL) && (splitsh->sh != NULL)) {
9830 smarktest(*splitsh);
9831 caveshlist->newindex((
void **) &parysh);
9835 }
else if (loc == ONEDGE) {
9838 spintet = *searchtet;
9840 eorgoppo(spintet, neightet);
9841 decode(neightet.tet[neightet.ver & 3], neightet);
9842 neightet.ver = epivot[neightet.ver];
9843 cavebdrylist->newindex((
void **) &parytet);
9844 *parytet = neightet;
9845 edestoppo(spintet, neightet);
9846 decode(neightet.tet[neightet.ver & 3], neightet);
9847 neightet.ver = epivot[neightet.ver];
9848 cavebdrylist->newindex((
void **) &parytet);
9849 *parytet = neightet;
9851 caveoldtetlist->newindex((
void **) &parytet);
9854 if (spintet.tet == searchtet->tet)
break;
9857 if (ivf->splitbdflag) {
9859 if ((splitseg != NULL) && (splitseg->sh != NULL)) {
9860 smarktest(*splitseg);
9861 splitseg->shver = 0;
9862 spivot(*splitseg, *splitsh);
9864 if (splitsh != NULL) {
9865 if (splitsh->sh != NULL) {
9867 pa = sorg(*splitsh);
9871 if (sorg(neighsh) != pa) {
9876 caveshlist->newindex((
void **) &parysh);
9879 cavesegshlist->newindex((
void **) &parysh);
9882 spivotself(neighsh);
9884 if (neighsh.sh == splitsh->sh)
break;
9885 if (neighsh.sh == NULL)
break;
9890 }
else if (loc == INSTAR) {
9894 for (i = 0; i < caveoldtetlist->objects; i++) {
9895 cavetet = (triface *) fastlookup(caveoldtetlist, i);
9897 for (j = 0; j < 4; j++) {
9898 decode(cavetet->tet[j], neightet);
9899 if (!infected(neightet)) {
9901 neightet.ver = epivot[neightet.ver];
9902 cavebdrylist->newindex((
void **) &parytet);
9903 *parytet = neightet;
9907 }
else if (loc == ONVERTEX) {
9913 if (ivf->assignmeshsize) {
9917 bgm->decode(point2bgmtet(org(*searchtet)), neightet);
9918 int bgmloc = (int) bgm->scoutpoint(insertpt, &neightet, 0);
9919 if (bgmloc != (
int) OUTSIDE) {
9920 insertpt[pointmtrindex] =
9921 bgm->getpointmeshsize(insertpt, &neightet, bgmloc);
9922 setpoint2bgmtet(insertpt, bgm->encode(neightet));
9925 insertpt[pointmtrindex] = getpointmeshsize(insertpt,searchtet,(
int)loc);
9931 swaplist = cavetetlist;
9932 cavetetlist = cavebdrylist;
9933 cavebdrylist = swaplist;
9934 for (i = 0; i < cavetetlist->objects; i++) {
9936 cavetet = (triface *) fastlookup(cavetetlist, i);
9938 if (!infected(*cavetet)) {
9943 if (!marktested(*cavetet)) {
9945 pts = (point *) cavetet->tet;
9946 if (pts[7] != dummypoint) {
9949 sign = orient4d_s(pts[4], pts[5], pts[6], pts[7], insertpt,
9950 pts[4][3], pts[5][3], pts[6][3], pts[7][3],
9953 sign = insphere_s(pts[4], pts[5], pts[6], pts[7], insertpt);
9955 enqflag = (sign < 0.0);
9959 ori = orient3d(pts[4], pts[5], pts[6], insertpt);
9964 }
else if (ori == 0.0) {
9968 decode(cavetet->tet[3], neineitet);
9969 if (!infected(neineitet)) {
9970 if (!marktested(neineitet)) {
9972 pts = (point *) neineitet.tet;
9974 sign = orient4d_s(pts[4],pts[5],pts[6],pts[7], insertpt,
9975 pts[4][3], pts[5][3], pts[6][3],
9976 pts[7][3], insertpt[3]);
9978 sign = insphere_s(pts[4],pts[5],pts[6],pts[7], insertpt);
9980 enqflag = (sign < 0.0);
9994 decode(cavetet->tet[3], neineitet);
9995 if (!infected(neineitet)) {
9996 if (!marktested(neineitet)) {
9998 pts = (point *) neineitet.tet;
10000 sign = orient4d_s(pts[4],pts[5],pts[6],pts[7], insertpt,
10001 pts[4][3], pts[5][3], pts[6][3],
10002 pts[7][3], insertpt[3]);
10004 sign = insphere_s(pts[4],pts[5],pts[6],pts[7], insertpt);
10006 enqflag = (sign < 0.0);
10015 marktest(*cavetet);
10020 k = (cavetet->ver & 3);
10021 for (j = 1; j < 4; j++) {
10022 decode(cavetet->tet[(j + k) % 4], neightet);
10023 cavetetlist->newindex((
void **) &parytet);
10024 *parytet = neightet;
10027 caveoldtetlist->newindex((
void **) &parytet);
10028 *parytet = *cavetet;
10031 cavetet->ver = epivot[cavetet->ver];
10032 cavebdrylist->newindex((
void **) &parytet);
10033 *parytet = *cavetet;
10038 cavetetlist->restart();
10041 if (checksubsegflag) {
10044 for (i = 0; i < caveoldtetlist->objects; i++) {
10045 cavetet = (triface *) fastlookup(caveoldtetlist, i);
10046 if ((ssptr = (shellface*) cavetet->tet[8]) != NULL) {
10047 for (j = 0; j < 6; j++) {
10049 sdecode(ssptr[j], checkseg);
10050 if (!sinfected(checkseg)) {
10052 cavetetseglist->newindex((
void **) &paryseg);
10053 *paryseg = checkseg;
10060 for (i = 0; i < cavetetseglist->objects; i++) {
10061 paryseg = (face *) fastlookup(cavetetseglist, i);
10062 suninfect(*paryseg);
10065 if (ivf->rejflag & 1) {
10068 for (i = 0; i < cavetetseglist->objects; i++) {
10069 paryseg1 = (face *) fastlookup(cavetetseglist, i);
10070 if (checkseg4encroach((point) paryseg1->sh[3], (point) paryseg1->sh[4],
10072 encseglist->newindex((
void **) &paryseg);
10073 *paryseg = *paryseg1;
10076 if ((ivf->rejflag & 1) && (encseglist->objects > 0)) {
10077 insertpoint_abort(splitseg, ivf);
10078 ivf->iloc = (int) ENCSEGMENT;
10084 if (checksubfaceflag) {
10087 for (i = 0; i < caveoldtetlist->objects; i++) {
10088 cavetet = (triface *) fastlookup(caveoldtetlist, i);
10089 if ((sptr = (shellface*) cavetet->tet[9]) != NULL) {
10090 for (j = 0; j < 4; j++) {
10092 sdecode(sptr[j], checksh);
10093 if (!sinfected(checksh)) {
10095 cavetetshlist->newindex((
void **) &parysh);
10103 for (i = 0; i < cavetetshlist->objects; i++) {
10104 parysh = (face *) fastlookup(cavetetshlist, i);
10105 suninfect(*parysh);
10108 if (ivf->rejflag & 2) {
10112 for (i = 0; i < cavetetshlist->objects; i++) {
10113 parysh = (face *) fastlookup(cavetetshlist, i);
10114 if (checkfac4encroach((point) parysh->sh[3], (point) parysh->sh[4],
10115 (point) parysh->sh[5], insertpt, cent, &rd)) {
10116 encshlist->newindex((
void **) &bface);
10117 bface->ss = *parysh;
10118 bface->forg = (point) parysh->sh[3];
10119 for (j = 0; j < 3; j++) bface->cent[j] = cent[j];
10123 if (encshlist->objects > 0) {
10124 insertpoint_abort(splitseg, ivf);
10125 ivf->iloc = (int) ENCSUBFACE;
10131 if ((ivf->iloc == (
int) OUTSIDE) && ivf->refineflag) {
10134 insertpoint_abort(splitseg, ivf);
10138 if (ivf->splitbdflag) {
10143 for (i = 0; i < caveshlist->objects; i++) {
10144 parysh = (face *) fastlookup(caveshlist, i);
10146 for (j = 0; j < 3; j++) {
10147 if (!isshsubseg(checksh)) {
10148 spivot(checksh, neighsh);
10149 if (!smarktested(neighsh)) {
10150 stpivot(neighsh, neightet);
10151 if (infected(neightet)) {
10152 fsymself(neightet);
10153 if (infected(neightet)) {
10158 sign = incircle3d(sorg(neighsh), sdest(neighsh),
10159 sapex(neighsh), insertpt);
10161 smarktest(neighsh);
10162 caveshlist->newindex((
void **) &parysh);
10169 senextself(checksh);
10174 if (ivf->validflag) {
10178 if (ivf->respectbdflag) {
10183 for (i = 0; i < cavetetshlist->objects; i++) {
10184 parysh = (face *) fastlookup(cavetetshlist, i);
10185 stpivot(*parysh, neightet);
10186 if (infected(neightet)) {
10187 fsymself(neightet);
10188 if (infected(neightet)) {
10190 if (!smarktested(*parysh)) {
10194 if (oppo(neightet) != dummypoint) {
10195 fsymself(neightet);
10197 if (oppo(neightet) != dummypoint) {
10198 ori = orient3d(org(neightet), dest(neightet), apex(neightet),
10202 fsymself(neightet);
10211 uninfect(neightet);
10212 unmarktest(neightet);
10214 neightet.ver = epivot[neightet.ver];
10215 cavebdrylist->newindex((
void **) &parytet);
10216 *parytet = neightet;
10218 for (j = 0; j < 3; j++) {
10219 esym(neightet, neineitet);
10220 neineitet.ver = epivot[neineitet.ver];
10221 cavebdrylist->newindex((
void **) &parytet);
10222 *parytet = neineitet;
10223 enextself(neightet);
10234 for (i = 0; i < cavetetseglist->objects; i++) {
10235 paryseg = (face *) fastlookup(cavetetseglist, i);
10237 if (!smarktested(*paryseg)) {
10238 sstpivot1(*paryseg, neightet);
10239 spintet = neightet;
10241 if (!infected(spintet))
break;
10242 fnextself(spintet);
10243 if (spintet.tet == neightet.tet)
break;
10245 if (infected(spintet)) {
10248 pa = org(neightet);
10249 pb = dest(neightet);
10250 spintet = neightet;
10254 pc = apex(spintet);
10255 if (pc != dummypoint) {
10256 ori = orient3d(pa, pb, pc, insertpt);
10259 esym(spintet, neineitet);
10260 pc = apex(neineitet);
10261 if (pc != dummypoint) {
10262 ori = orient3d(pb, pa, pc, insertpt);
10271 fnextself(spintet);
10272 if (spintet.tet == neightet.tet)
break;
10276 terminatetetgen(
this, 2);
10278 neightet = spintet;
10279 if (b->verbose > 3) {
10280 printf(
" Cut tet (%d, %d, %d, %d)\n",
10281 pointmark(org(neightet)), pointmark(dest(neightet)),
10282 pointmark(apex(neightet)), pointmark(oppo(neightet)));
10284 uninfect(neightet);
10285 unmarktest(neightet);
10287 neightet.ver = epivot[neightet.ver];
10288 cavebdrylist->newindex((
void **) &parytet);
10289 *parytet = neightet;
10291 for (j = 0; j < 3; j++) {
10292 esym(neightet, neineitet);
10293 neineitet.ver = epivot[neineitet.ver];
10294 cavebdrylist->newindex((
void **) &parytet);
10295 *parytet = neineitet;
10296 enextself(neightet);
10304 for (i = 0; i < cavebdrylist->objects; i++) {
10305 cavetet = (triface *) fastlookup(cavebdrylist, i);
10308 fsym(*cavetet, neightet);
10309 if (infected(neightet)) {
10310 if (apex(*cavetet) != dummypoint) {
10312 if (oppo(neightet) != dummypoint) {
10314 if (issubface(neightet)) {
10317 pa = org(*cavetet);
10318 pb = dest(*cavetet);
10319 pc = apex(*cavetet);
10320 volume = orient3dfast(pa, pb, pc, insertpt);
10321 attrib = distance(pa, pb) * distance(pb, pc) * distance(pc, pa);
10322 if ((fabs(volume) / attrib) < b->epsilon) {
10325 ori = orient3d(pa, pb, pc, insertpt);
10328 ori = orient3d(org(*cavetet), dest(*cavetet), apex(*cavetet),
10331 enqflag = (ori > 0);
10344 cavetetlist->newindex((
void **) &parytet);
10345 *parytet = *cavetet;
10347 uninfect(neightet);
10348 unmarktest(neightet);
10351 for (j = 0; j < 3; j++) {
10352 esym(neightet, neineitet);
10353 neineitet.ver = epivot[neineitet.ver];
10354 cavebdrylist->newindex((
void **) &parytet);
10355 *parytet = neineitet;
10356 enextself(neightet);
10359 unmarktest(*cavetet);
10363 unmarktest(*cavetet);
10367 if (cutcount > 0) {
10370 cavebdrylist->restart();
10371 for (i = 0; i < cavetetlist->objects; i++) {
10372 cavetet = (triface *) fastlookup(cavetetlist, i);
10374 fsym(*cavetet, neightet);
10375 if (infected(neightet)) {
10377 cavebdrylist->newindex((
void **) &parytet);
10378 *parytet = *cavetet;
10381 unmarktest(*cavetet);
10386 cavetetlist->restart();
10387 for (i = 0; i < caveoldtetlist->objects; i++) {
10388 cavetet = (triface *) fastlookup(caveoldtetlist, i);
10389 if (infected(*cavetet)) {
10390 cavetetlist->newindex((
void **) &parytet);
10391 *parytet = *cavetet;
10395 swaplist = caveoldtetlist;
10396 caveoldtetlist = cavetetlist;
10397 cavetetlist = swaplist;
10400 if (caveoldtetlist->objects == 0l) {
10401 insertpoint_abort(splitseg, ivf);
10402 ivf->iloc = (int) BADELEMENT;
10406 if (ivf->splitbdflag) {
10407 int cutshcount = 0;
10409 for (i = 0; i < caveshlist->objects; i++) {
10410 parysh = (face *) fastlookup(caveshlist, i);
10411 if (smarktested(*parysh)) {
10413 stpivot(*parysh, neightet);
10414 if (infected(neightet)) {
10415 fsymself(neightet);
10416 if (infected(neightet)) {
10421 sunmarktest(*parysh);
10423 j = caveshlist->objects - 1;
10424 checksh = * (face *) fastlookup(caveshlist, j);
10427 caveshlist->objects--;
10433 if (cutshcount > 0) {
10436 if (loc == ONFACE) {
10437 if ((splitsh != NULL) && (splitsh->sh != NULL)) {
10439 if (!smarktested(*splitsh)) i++;
10441 }
else if (loc == ONEDGE) {
10442 if ((splitseg != NULL) && (splitseg->sh != NULL)) {
10444 if (!smarktested(*splitseg)) i++;
10446 if ((splitsh != NULL) && (splitsh->sh != NULL)) {
10448 pa = sorg(*splitsh);
10449 neighsh = *splitsh;
10452 if (sorg(neighsh) != pa) {
10453 sesymself(neighsh);
10456 if (!smarktested(neighsh)) i++;
10458 spivotself(neighsh);
10460 if (neighsh.sh == splitsh->sh)
break;
10461 if (neighsh.sh == NULL)
break;
10468 insertpoint_abort(splitseg, ivf);
10469 ivf->iloc = (int) BADELEMENT;
10478 if (ivf->refineflag) {
10483 if (((ivf->refineflag == 1) && !infected(ivf->refinetet)) ||
10484 ((ivf->refineflag == 2) && !smarktested(ivf->refinesh))) {
10485 insertpoint_abort(splitseg, ivf);
10486 ivf->iloc = (int) BADELEMENT;
10491 if (b->plc && (loc != INSTAR)) {
10495 if (loc == OUTSIDE) {
10496 pts = (point *) &(searchtet->tet[4]);
10497 for (i = 0; i < 3; i++) {
10498 cavetetvertlist->newindex((
void **) &parypt);
10501 }
else if (loc == INTETRAHEDRON) {
10502 pts = (point *) &(searchtet->tet[4]);
10503 for (i = 0; i < 4; i++) {
10504 cavetetvertlist->newindex((
void **) &parypt);
10507 }
else if (loc == ONFACE) {
10508 pts = (point *) &(searchtet->tet[4]);
10509 for (i = 0; i < 3; i++) {
10510 cavetetvertlist->newindex((
void **) &parypt);
10513 if (pts[3] != dummypoint) {
10514 cavetetvertlist->newindex((
void **) &parypt);
10517 fsym(*searchtet, spintet);
10518 if (oppo(spintet) != dummypoint) {
10519 cavetetvertlist->newindex((
void **) &parypt);
10520 *parypt = oppo(spintet);
10522 }
else if (loc == ONEDGE) {
10523 spintet = *searchtet;
10524 cavetetvertlist->newindex((
void **) &parypt);
10525 *parypt = org(spintet);
10526 cavetetvertlist->newindex((
void **) &parypt);
10527 *parypt = dest(spintet);
10529 if (apex(spintet) != dummypoint) {
10530 cavetetvertlist->newindex((
void **) &parypt);
10531 *parypt = apex(spintet);
10533 fnextself(spintet);
10534 if (spintet.tet == searchtet->tet)
break;
10538 int rejptflag = (ivf->rejflag & 4);
10542 for (i = 0; i < cavetetvertlist->objects; i++) {
10543 parypt = (point *) fastlookup(cavetetvertlist, i);
10544 rd = distance(*parypt, insertpt);
10546 if (rd < minedgelength) {
10553 if (rd < (0.5 * (*parypt)[pointmtrindex])) {
10560 cavetetvertlist->restart();
10565 if (loc == NEARVERTEX) {
10566 if (!issteinerpoint(insertpt) && b->nomergevertex) {
10570 printf(
"Warning: Two points, %d and %d, are very close.\n",
10571 pointmark(insertpt), pointmark(*pts));
10572 printf(
" Creating a very short edge (len = %g) (< %g).\n",
10573 rd, minedgelength);
10574 printf(
" You may try a smaller tolerance (-T) (current is %g)\n",
10576 printf(
" to avoid this warning.\n");
10579 point2tetorg(*pts, *searchtet);
10580 insertpoint_abort(splitseg, ivf);
10581 ivf->iloc = (int) loc;
10586 point2tetorg(*pts, *searchtet);
10587 insertpoint_abort(splitseg, ivf);
10588 ivf->iloc = (int) loc;
10594 if (b->weighted || ivf->cdtflag || ivf->smlenflag
10598 for (i = 0; i < caveoldtetlist->objects; i++) {
10599 cavetet = (triface *) fastlookup(caveoldtetlist, i);
10601 pts = (point *) &(cavetet->tet[4]);
10602 for (j = 0; j < 4; j++) {
10603 if (pts[j] != dummypoint) {
10604 if (!pinfected(pts[j])) {
10606 cavetetvertlist->newindex((
void **) &parypt);
10613 for (i = 0; i < cavetetvertlist->objects; i++) {
10614 parypt = (point *) fastlookup(cavetetvertlist, i);
10615 puninfect(*parypt);
10617 if (ivf->smlenflag) {
10620 parypt = (point *) fastlookup(cavetetvertlist, 0);
10621 ivf->smlen = distance(*parypt, insertpt);
10622 ivf->parentpt = *parypt;
10623 for (i = 1; i < cavetetvertlist->objects; i++) {
10624 parypt = (point *) fastlookup(cavetetvertlist, i);
10625 len = distance(*parypt, insertpt);
10626 if (len < ivf->smlen) {
10628 ivf->parentpt = *parypt;
10635 if (ivf->cdtflag) {
10637 for (i = 0; i < caveoldtetlist->objects; i++) {
10638 cavetet = (triface *) fastlookup(caveoldtetlist, i);
10639 unmarktest(*cavetet);
10641 for (i = 0; i < cavebdrylist->objects; i++) {
10642 cavetet = (triface *) fastlookup(cavebdrylist, i);
10643 unmarktest(*cavetet);
10646 cavetetlist->restart();
10647 if (checksubsegflag) {
10648 cavetetseglist->restart();
10650 if (checksubfaceflag) {
10651 cavetetshlist->restart();
10661 if (checksubsegflag) {
10662 for (i = 0; i < cavetetseglist->objects; i++) {
10663 paryseg = (face *) fastlookup(cavetetseglist, i);
10665 if (!smarktested(*paryseg)) {
10670 sstpivot1(*paryseg, neightet);
10671 spintet = neightet;
10674 if (!infected(spintet)) {
10675 neineitet = spintet;
10679 fnextself(spintet);
10680 if (spintet.tet == neightet.tet)
break;
10686 s = cavetetseglist->objects - 1;
10687 checkseg = * (face *) fastlookup(cavetetseglist, s);
10688 *paryseg = checkseg;
10689 cavetetseglist->objects--;
10691 }
else if (k < j) {
10693 sstbond1(*paryseg, neineitet);
10696 if (!ivf->splitbdflag) {
10697 checkseg = *paryseg;
10699 caveencseglist->newindex((
void **) &paryseg);
10700 *paryseg = checkseg;
10703 terminatetetgen(
this, 2);
10715 if (checksubfaceflag) {
10716 for (i = 0; i < cavetetshlist->objects; i++) {
10717 parysh = (face *) fastlookup(cavetetshlist, i);
10719 if (!smarktested(*parysh)) {
10722 for (j = 0; j < 2; j++) {
10723 stpivot(*parysh, neightet);
10724 if (!infected(neightet)) {
10729 sesymself(*parysh);
10733 s = cavetetshlist->objects - 1;
10734 checksh = * (face *) fastlookup(cavetetshlist, s);
10736 cavetetshlist->objects--;
10738 }
else if (k == 1) {
10742 if (!ivf->splitbdflag) {
10745 caveencshlist->newindex((
void **) &parysh);
10749 terminatetetgen(
this, 2);
10763 for (i = 0; i < cavebdrylist->objects; i++) {
10764 cavetet = (triface *) fastlookup(cavebdrylist, i);
10765 neightet = *cavetet;
10766 unmarktest(neightet);
10768 fsym(neightet, oldtet);
10769 if (apex(neightet) != dummypoint) {
10771 maketetrahedron(&newtet);
10772 setorg(newtet, dest(neightet));
10773 setdest(newtet, org(neightet));
10774 setapex(newtet, apex(neightet));
10775 setoppo(newtet, insertpt);
10779 maketetrahedron(&newtet);
10780 setorg(newtet, org(neightet));
10781 setdest(newtet, dest(neightet));
10782 setapex(newtet, insertpt);
10783 setoppo(newtet, dummypoint);
10788 for (j = 0; j < numelemattrib; j++) {
10789 attrib = elemattribute(oldtet.tet, j);
10790 setelemattribute(newtet.tet, j, attrib);
10792 if (b->varvolume) {
10793 volume = volumebound(oldtet.tet);
10794 setvolumebound(newtet.tet, volume);
10797 bond(newtet, neightet);
10803 recenttet = newtet;
10805 setpoint2tet(insertpt, (tetrahedron) (newtet.tet));
10808 cavetetlist->restart();
10811 for (i = 0; i < cavebdrylist->objects; i++) {
10812 cavetet = (triface *) fastlookup(cavebdrylist, i);
10815 fsym(oldtet, neightet);
10816 fsym(neightet, newtet);
10819 for (j = 0; j < 3; j++) {
10820 esym(newtet, neightet);
10821 if (neightet.tet[neightet.ver & 3] == NULL) {
10825 fnextself(spintet);
10826 if (!infected(spintet))
break;
10828 fsym(spintet, newneitet);
10829 esymself(newneitet);
10830 bond(neightet, newneitet);
10831 if (ivf->lawson > 1) {
10832 cavetetlist->newindex((
void **) &parytet);
10833 *parytet = neightet;
10837 setpoint2tet(org(newtet), (tetrahedron) (newtet.tet));
10844 if (checksubfaceflag) {
10846 for (i = 0; i < cavetetshlist->objects; i++) {
10847 parysh = (face *) fastlookup(cavetetshlist, i);
10849 if (!sinfected(*parysh)) {
10850 stpivot(*parysh, neightet);
10851 fsym(neightet, spintet);
10852 sesymself(*parysh);
10853 tsbond(spintet, *parysh);
10858 if (checksubsegflag) {
10860 for (i = 0; i < cavetetseglist->objects; i++) {
10861 paryseg = (face *) fastlookup(cavetetseglist, i);
10863 if (!sinfected(*paryseg)) {
10864 sstpivot1(*paryseg, neightet);
10865 spintet = neightet;
10867 tssbond1(spintet, *paryseg);
10868 fnextself(spintet);
10869 if (spintet.tet == neightet.tet)
break;
10875 if (((splitsh != NULL) && (splitsh->sh != NULL)) ||
10876 ((splitseg != NULL) && (splitseg->sh != NULL))) {
10878 sinsertvertex(insertpt, splitsh, splitseg, ivf->sloc, ivf->sbowywat, 0);
10881 if (checksubfaceflag) {
10882 if (ivf->splitbdflag) {
10884 for (i = 0; i < caveshbdlist->objects; i++) {
10886 parysh = (face *) fastlookup(caveshbdlist, i);
10887 spivot(*parysh, checksh);
10889 if (checksh.sh[3] != NULL) {
10892 stpivot(*parysh, neightet);
10894 spintet = neightet;
10896 fnextself(spintet);
10897 if (!infected(spintet))
break;
10900 fsym(spintet, neightet);
10902 spintet = neightet;
10904 fnextself(spintet);
10905 if (apex(spintet) == insertpt)
break;
10908 if (sorg(checksh) != org(spintet)) {
10909 sesymself(checksh);
10912 tsbond(spintet, checksh);
10914 sesymself(checksh);
10915 tsbond(spintet, checksh);
10921 for (i = 0; i < caveshbdlist->objects; i++) {
10923 parysh = (face *) fastlookup(caveshbdlist, i);
10924 spivot(*parysh, checksh);
10926 if (checksh.sh[3] != NULL) {
10927 subfacstack->newindex((
void **) &parysh);
10932 for (i = 0; i < caveencshlist->objects; i++) {
10933 parysh = (face *) fastlookup(caveencshlist, i);
10936 if (!smarktested(*parysh)) {
10938 suninfect(checksh);
10939 stdissolve(checksh);
10940 subfacstack->newindex((
void **) &parysh);
10947 if (checksubsegflag) {
10948 if (ivf->splitbdflag) {
10949 if (splitseg != NULL) {
10951 for (i = 0; i < cavesegshlist->objects; i++) {
10952 paryseg = (face *) fastlookup(cavesegshlist, i);
10954 checkseg = *paryseg;
10956 checkseg.shver = 0;
10957 spivot(checkseg, checksh);
10958 if (checksh.sh != NULL) {
10960 stpivot(checksh, neightet);
10963 point2tetorg(sorg(checkseg), neightet);
10964 finddirection(&neightet, sdest(checkseg));
10966 sstbond1(checkseg, neightet);
10967 spintet = neightet;
10969 tssbond1(spintet, checkseg);
10970 fnextself(spintet);
10971 if (spintet.tet == neightet.tet)
break;
10978 if (splitseg != NULL) {
10980 for (i = 0; i < cavesegshlist->objects; i++) {
10981 paryseg = (face *) fastlookup(cavesegshlist, i);
10982 checkseg = *paryseg;
10984 s = randomnation(subsegstack->objects + 1);
10985 subsegstack->newindex((
void **) &paryseg);
10986 *paryseg = * (face *) fastlookup(subsegstack, s);
10987 paryseg = (face *) fastlookup(subsegstack, s);
10988 *paryseg = checkseg;
10991 for (i = 0; i < caveencseglist->objects; i++) {
10992 paryseg = (face *) fastlookup(caveencseglist, i);
10993 if (!smarktested(*paryseg)) {
10994 checkseg = *paryseg;
10995 suninfect(checkseg);
10996 sstdissolve1(checkseg);
10997 s = randomnation(subsegstack->objects + 1);
10998 subsegstack->newindex((
void **) &paryseg);
10999 *paryseg = * (face *) fastlookup(subsegstack, s);
11000 paryseg = (face *) fastlookup(subsegstack, s);
11001 *paryseg = checkseg;
11013 for (i = 0; i < cavetetvertlist->objects; i++) {
11014 pts = (point *) fastlookup(cavetetvertlist, i);
11015 decode(point2tet(*pts), *searchtet);
11016 if (infected(*searchtet)) {
11018 if (b->verbose > 1) {
11019 printf(
" Point #%d is non-regular after the insertion of #%d.\n",
11020 pointmark(*pts), pointmark(insertpt));
11022 setpointtype(*pts, NREGULARVERTEX);
11029 if (ivf->chkencflag & 1) {
11031 for (i = 0; i < cavetetseglist->objects; i++) {
11032 paryseg = (face *) fastlookup(cavetetseglist, i);
11034 if (!sinfected(*paryseg)) {
11035 enqueuesubface(badsubsegs, paryseg);
11038 if (splitseg != NULL) {
11040 for (i = 0; i < cavesegshlist->objects; i++) {
11041 paryseg = (face *) fastlookup(cavesegshlist, i);
11042 enqueuesubface(badsubsegs, paryseg);
11047 if (ivf->chkencflag & 2) {
11049 for (i = 0; i < cavetetshlist->objects; i++) {
11050 parysh = (face *) fastlookup(cavetetshlist, i);
11052 if (!sinfected(*parysh)) {
11053 enqueuesubface(badsubfacs, parysh);
11057 for (i = 0; i < caveshbdlist->objects; i++) {
11059 parysh = (face *) fastlookup(caveshbdlist, i);
11060 spivot(*parysh, checksh);
11062 if (checksh.sh[3] != NULL) {
11063 enqueuesubface(badsubfacs, &checksh);
11068 if (ivf->chkencflag & 4) {
11070 for (i = 0; i < cavebdrylist->objects; i++) {
11071 cavetet = (triface *) fastlookup(cavebdrylist, i);
11072 enqueuetetrahedron(cavetet);
11079 for (i = 0; i < caveoldtetlist->objects; i++) {
11080 searchtet = (triface *) fastlookup(caveoldtetlist, i);
11081 if (ishulltet(*searchtet)) {
11084 tetrahedrondealloc(searchtet->tet);
11087 if (((splitsh != NULL) && (splitsh->sh != NULL)) ||
11088 ((splitseg != NULL) && (splitseg->sh != NULL))) {
11090 for (i = 0; i < caveshlist->objects; i++) {
11091 parysh = (face *) fastlookup(caveshlist, i);
11092 if (checksubfaceflag) {
11096 stpivot(*parysh, neightet);
11097 if (neightet.tet != NULL) {
11098 if (neightet.tet[4] != NULL) {
11100 tsdissolve(neightet);
11101 fsymself(neightet);
11102 tsdissolve(neightet);
11106 shellfacedealloc(subfaces, parysh->sh);
11108 if ((splitseg != NULL) && (splitseg->sh != NULL)) {
11110 shellfacedealloc(subsegs, splitseg->sh);
11115 for (i = 0; i < cavebdrylist->objects; i++) {
11116 searchtet = (triface *) fastlookup(cavebdrylist, i);
11117 flippush(flipstack, searchtet);
11119 if (ivf->lawson > 1) {
11120 for (i = 0; i < cavetetlist->objects; i++) {
11121 searchtet = (triface *) fastlookup(cavetetlist, i);
11122 flippush(flipstack, searchtet);
11130 caveoldtetlist->restart();
11131 cavebdrylist->restart();
11132 cavetetlist->restart();
11134 if (checksubsegflag) {
11135 cavetetseglist->restart();
11136 caveencseglist->restart();
11139 if (checksubfaceflag) {
11140 cavetetshlist->restart();
11141 caveencshlist->restart();
11144 if (b->weighted || ivf->smlenflag
11146 cavetetvertlist->restart();
11149 if (((splitsh != NULL) && (splitsh->sh != NULL)) ||
11150 ((splitseg != NULL) && (splitseg->sh != NULL))) {
11151 caveshlist->restart();
11152 caveshbdlist->restart();
11153 cavesegshlist->restart();
11167 void tetgenmesh::insertpoint_abort(face *splitseg, insertvertexflags *ivf)
11173 for (i = 0; i < caveoldtetlist->objects; i++) {
11174 cavetet = (triface *) fastlookup(caveoldtetlist, i);
11175 uninfect(*cavetet);
11176 unmarktest(*cavetet);
11178 for (i = 0; i < cavebdrylist->objects; i++) {
11179 cavetet = (triface *) fastlookup(cavebdrylist, i);
11180 unmarktest(*cavetet);
11182 cavetetlist->restart();
11183 cavebdrylist->restart();
11184 caveoldtetlist->restart();
11185 cavetetseglist->restart();
11186 cavetetshlist->restart();
11187 if (ivf->splitbdflag) {
11188 if ((splitseg != NULL) && (splitseg->sh != NULL)) {
11189 sunmarktest(*splitseg);
11191 for (i = 0; i < caveshlist->objects; i++) {
11192 parysh = (face *) fastlookup(caveshlist, i);
11193 sunmarktest(*parysh);
11195 caveshlist->restart();
11196 cavesegshlist->restart();
11219 void tetgenmesh::transfernodes()
11232 for (i = 0; i < in->numberofpoints; i++) {
11233 makepoint(&pointloop, UNUSEDVERTEX);
11235 x = pointloop[0] = in->pointlist[coordindex++];
11236 y = pointloop[1] = in->pointlist[coordindex++];
11237 z = pointloop[2] = in->pointlist[coordindex++];
11239 for (j = 0; j < in->numberofpointattributes; j++) {
11240 pointloop[3 + j] = in->pointattributelist[attribindex++];
11243 for (j = 0; j < in->numberofpointmtrs; j++) {
11244 pointloop[pointmtrindex + j] = in->pointmtrlist[mtrindex++];
11247 if (in->numberofpointattributes > 0) {
11255 if (w < fabs(y)) w = fabs(y);
11256 if (w < fabs(z)) w = fabs(z);
11258 if (b->weighted_param == 0) {
11259 pointloop[3] = x * x + y * y + z * z - w;
11270 xmin = (x < xmin) ? x : xmin;
11271 xmax = (x > xmax) ? x : xmax;
11272 ymin = (y < ymin) ? y : ymin;
11273 ymax = (y > ymax) ? y : ymax;
11274 zmin = (z < zmin) ? z : zmin;
11275 zmax = (z > zmax) ? z : zmax;
11279 setpointgeomuv(pointloop, 0, in->pointparamlist[i].uv[0]);
11280 setpointgeomuv(pointloop, 1, in->pointparamlist[i].uv[1]);
11281 setpointgeomtag(pointloop, in->pointparamlist[i].tag);
11282 if (in->pointparamlist[i].type == 0) {
11283 setpointtype(pointloop, RIDGEVERTEX);
11284 }
else if (in->pointparamlist[i].type == 1) {
11285 setpointtype(pointloop, FREESEGVERTEX);
11286 }
else if (in->pointparamlist[i].type == 2) {
11287 setpointtype(pointloop, FREEFACETVERTEX);
11288 }
else if (in->pointparamlist[i].type == 3) {
11289 setpointtype(pointloop, FREEVOLVERTEX);
11298 longest = sqrt(x * x + y * y + z * z);
11299 if (longest == 0.0) {
11300 printf(
"Error: The point set is trivial.\n");
11301 terminatetetgen(
this, 10);
11304 minedgelength = longest * b->epsilon;
11323 void tetgenmesh::hilbert_init(
int n)
11325 int gc[8], N, mask, travel_bit;
11330 N = (n == 2) ? 4 : 8;
11331 mask = (n == 2) ? 3 : 7;
11334 for (i = 0; i < N; i++) {
11335 gc[i] = i ^ (i >> 1);
11338 for (e = 0; e < N; e++) {
11339 for (d = 0; d < n; d++) {
11343 travel_bit = e ^ f;
11344 for (i = 0; i < N; i++) {
11346 k = gc[i] * (travel_bit * 2);
11347 g = ((k | (k / N)) & mask);
11349 transgc[e][d][i] = (g ^ e);
11356 for (i = 1; i < N; i++) {
11358 v = (v ^ (v - 1)) >> 1;
11359 for (c = 0; v; c++) {
11362 tsb1mod3[i] = c % n;
11372 int tetgenmesh::hilbert_split(point* vertexarray,
int arraysize,
int gc0,
int gc1,
11373 REAL bxmin, REAL bxmax, REAL bymin, REAL bymax,
11374 REAL bzmin, REAL bzmax)
11384 axis = (gc0 ^ gc1) >> 1;
11388 split = 0.5 * (bxmin + bxmax);
11389 }
else if (axis == 1) {
11390 split = 0.5 * (bymin + bymax);
11392 split = 0.5 * (bzmin + bzmax);
11397 d = ((gc0 & (1<<axis)) == 0) ? 1 : -1;
11408 for (; i < arraysize; i++) {
11409 if (vertexarray[i][axis] >= split)
break;
11411 for (; j >= 0; j--) {
11412 if (vertexarray[j][axis] < split)
break;
11415 if (i == (j + 1))
break;
11417 swapvert = vertexarray[i];
11418 vertexarray[i] = vertexarray[j];
11419 vertexarray[j] = swapvert;
11424 for (; i < arraysize; i++) {
11425 if (vertexarray[i][axis] <= split)
break;
11427 for (; j >= 0; j--) {
11428 if (vertexarray[j][axis] > split)
break;
11431 if (i == (j + 1))
break;
11433 swapvert = vertexarray[i];
11434 vertexarray[i] = vertexarray[j];
11435 vertexarray[j] = swapvert;
11443 void tetgenmesh::hilbert_sort3(point* vertexarray,
int arraysize,
int e,
int d,
11444 REAL bxmin, REAL bxmax, REAL bymin, REAL bymax,
11445 REAL bzmin, REAL bzmax,
int depth)
11447 REAL x1, x2, y1, y2, z1, z2;
11448 int p[9], w, e_w, d_w, k, ei, di;
11449 int n = 3, mask = 7;
11455 p[4] = hilbert_split(vertexarray, p[8], transgc[e][d][3], transgc[e][d][4],
11456 bxmin, bxmax, bymin, bymax, bzmin, bzmax);
11457 p[2] = hilbert_split(vertexarray, p[4], transgc[e][d][1], transgc[e][d][2],
11458 bxmin, bxmax, bymin, bymax, bzmin, bzmax);
11459 p[1] = hilbert_split(vertexarray, p[2], transgc[e][d][0], transgc[e][d][1],
11460 bxmin, bxmax, bymin, bymax, bzmin, bzmax);
11461 p[3] = hilbert_split(&(vertexarray[p[2]]), p[4] - p[2],
11462 transgc[e][d][2], transgc[e][d][3],
11463 bxmin, bxmax, bymin, bymax, bzmin, bzmax) + p[2];
11464 p[6] = hilbert_split(&(vertexarray[p[4]]), p[8] - p[4],
11465 transgc[e][d][5], transgc[e][d][6],
11466 bxmin, bxmax, bymin, bymax, bzmin, bzmax) + p[4];
11467 p[5] = hilbert_split(&(vertexarray[p[4]]), p[6] - p[4],
11468 transgc[e][d][4], transgc[e][d][5],
11469 bxmin, bxmax, bymin, bymax, bzmin, bzmax) + p[4];
11470 p[7] = hilbert_split(&(vertexarray[p[6]]), p[8] - p[6],
11471 transgc[e][d][6], transgc[e][d][7],
11472 bxmin, bxmax, bymin, bymax, bzmin, bzmax) + p[6];
11474 if (b->hilbert_order > 0) {
11476 if ((depth + 1) == b->hilbert_order) {
11483 for (w = 0; w < 8; w++) {
11488 if ((p[w+1] - p[w]) > b->hilbert_limit) {
11495 k = 2 * ((w - 1) / 2);
11496 e_w = k ^ (k >> 1);
11499 e_w = ((k << (d+1)) & mask) | ((k >> (n-d-1)) & mask);
11506 d_w = ((w % 2) == 0) ? tsb1mod3[w - 1] : tsb1mod3[w];
11508 di = (d + d_w + 1) % n;
11510 if (transgc[e][d][w] & 1) {
11511 x1 = 0.5 * (bxmin + bxmax);
11515 x2 = 0.5 * (bxmin + bxmax);
11517 if (transgc[e][d][w] & 2) {
11518 y1 = 0.5 * (bymin + bymax);
11522 y2 = 0.5 * (bymin + bymax);
11524 if (transgc[e][d][w] & 4) {
11525 z1 = 0.5 * (bzmin + bzmax);
11529 z2 = 0.5 * (bzmin + bzmax);
11531 hilbert_sort3(&(vertexarray[p[w]]), p[w+1] - p[w], ei, di,
11532 x1, x2, y1, y2, z1, z2, depth+1);
11543 void tetgenmesh::brio_multiscale_sort(point* vertexarray,
int arraysize,
11544 int threshold, REAL ratio,
int *depth)
11549 if (arraysize >= threshold) {
11551 middle = arraysize * ratio;
11552 brio_multiscale_sort(vertexarray, middle, threshold, ratio, depth);
11555 hilbert_sort3(&(vertexarray[middle]), arraysize - middle, 0, 0,
11556 xmin, xmax, ymin, ymax, zmin, zmax, 0);
11565 unsigned long tetgenmesh::randomnation(
unsigned int choices)
11567 unsigned long newrandom;
11569 if (choices >= 714025l) {
11570 newrandom = (randomseed * 1366l + 150889l) % 714025l;
11571 randomseed = (newrandom * 1366l + 150889l) % 714025l;
11572 newrandom = newrandom * (choices / 714025l) + randomseed;
11573 if (newrandom >= choices) {
11574 return newrandom - choices;
11579 randomseed = (randomseed * 1366l + 150889l) % 714025l;
11580 return randomseed % choices;
11595 void tetgenmesh::randomsample(point searchpt,triface *searchtet)
11597 tetrahedron *firsttet, *tetptr;
11599 void **sampleblock;
11600 uintptr_t alignptr;
11601 long sampleblocks, samplesperblock, samplenum;
11602 long tetblocks, i, j;
11603 REAL searchdist, dist;
11605 if (b->verbose > 2) {
11606 printf(
" Random sampling tetrahedra for searching point %d.\n",
11607 pointmark(searchpt));
11611 if (searchtet->tet == NULL) {
11613 *searchtet = recenttet;
11618 searchtet->ver = 3;
11620 torg = org(*searchtet);
11621 searchdist = (searchpt[0] - torg[0]) * (searchpt[0] - torg[0]) +
11622 (searchpt[1] - torg[1]) * (searchpt[1] - torg[1]) +
11623 (searchpt[2] - torg[2]) * (searchpt[2] - torg[2]);
11627 if (recenttet.tet != searchtet->tet) {
11629 torg = org(recenttet);
11630 dist = (searchpt[0] - torg[0]) * (searchpt[0] - torg[0]) +
11631 (searchpt[1] - torg[1]) * (searchpt[1] - torg[1]) +
11632 (searchpt[2] - torg[2]) * (searchpt[2] - torg[2]);
11633 if (dist < searchdist) {
11634 *searchtet = recenttet;
11640 searchdist = longest;
11646 while (samples * samples * samples * samples < tetrahedrons->items) {
11650 tetblocks = (tetrahedrons->maxitems + b->tetrahedraperblock - 1)
11651 / b->tetrahedraperblock;
11653 samplesperblock = 1 + (samples / tetblocks);
11654 sampleblocks = samples / samplesperblock;
11655 sampleblock = tetrahedrons->firstblock;
11656 for (i = 0; i < sampleblocks; i++) {
11657 alignptr = (uintptr_t) (sampleblock + 1);
11658 firsttet = (tetrahedron *)
11659 (alignptr + (uintptr_t) tetrahedrons->alignbytes
11660 - (alignptr % (uintptr_t) tetrahedrons->alignbytes));
11661 for (j = 0; j < samplesperblock; j++) {
11662 if (i == tetblocks - 1) {
11664 samplenum = randomnation((
int)
11665 (tetrahedrons->maxitems - (i * b->tetrahedraperblock)));
11667 samplenum = randomnation(b->tetrahedraperblock);
11669 tetptr = (tetrahedron *)
11670 (firsttet + (samplenum * tetrahedrons->itemwords));
11671 torg = (point) tetptr[4];
11672 if (torg != (point) NULL) {
11673 dist = (searchpt[0] - torg[0]) * (searchpt[0] - torg[0]) +
11674 (searchpt[1] - torg[1]) * (searchpt[1] - torg[1]) +
11675 (searchpt[2] - torg[2]) * (searchpt[2] - torg[2]);
11676 if (dist < searchdist) {
11677 searchtet->tet = tetptr;
11678 searchtet->ver = 11;
11683 if (i != tetblocks - 1) j--;
11686 sampleblock = (
void **) *sampleblock;
11712 enum tetgenmesh::locateresult
11713 tetgenmesh::locate(point searchpt, triface* searchtet,
int chkencflag)
11715 point torg, tdest, tapex, toppo;
11716 enum {ORGMOVE, DESTMOVE, APEXMOVE} nextmove;
11717 REAL ori, oriorg, oridest, oriapex;
11718 enum locateresult loc = OUTSIDE;
11722 torg = tdest = tapex = toppo = NULL;
11724 if (searchtet->tet == NULL) {
11726 searchtet->tet = recenttet.tet;
11730 if (ishulltet(*searchtet)) {
11732 searchtet->ver = 3;
11733 fsymself(*searchtet);
11737 for (searchtet->ver = 0; searchtet->ver < 4; searchtet->ver++) {
11738 torg = org(*searchtet);
11739 tdest = dest(*searchtet);
11740 tapex = apex(*searchtet);
11741 ori = orient3d(torg, tdest, tapex, searchpt);
11742 if (ori < 0.0)
break;
11744 if (searchtet->ver == 4) {
11745 terminatetetgen(
this, 2);
11751 toppo = oppo(*searchtet);
11754 if (toppo == searchpt) {
11756 esymself(*searchtet);
11757 eprevself(*searchtet);
11763 oriorg = orient3d(tdest, tapex, toppo, searchpt);
11764 oridest = orient3d(tapex, torg, toppo, searchpt);
11765 oriapex = orient3d(torg, tdest, toppo, searchpt);
11773 s = randomnation(3);
11775 nextmove = ORGMOVE;
11776 }
else if (s == 1) {
11777 nextmove = DESTMOVE;
11779 nextmove = APEXMOVE;
11784 if (randomnation(2)) {
11785 nextmove = ORGMOVE;
11787 nextmove = DESTMOVE;
11794 if (randomnation(2)) {
11795 nextmove = ORGMOVE;
11797 nextmove = APEXMOVE;
11801 nextmove = ORGMOVE;
11809 if (randomnation(2)) {
11810 nextmove = DESTMOVE;
11812 nextmove = APEXMOVE;
11816 nextmove = DESTMOVE;
11821 nextmove = APEXMOVE;
11827 enextesymself(*searchtet);
11828 if (oridest == 0) {
11829 eprevself(*searchtet);
11830 if (oriapex == 0) {
11838 if (oriapex == 0) {
11839 enextself(*searchtet);
11846 if (oridest == 0) {
11848 eprevesymself(*searchtet);
11849 if (oriapex == 0) {
11850 eprevself(*searchtet);
11857 if (oriapex == 0) {
11859 esymself(*searchtet);
11863 loc = INTETRAHEDRON;
11870 if (nextmove == ORGMOVE) {
11871 enextesymself(*searchtet);
11872 }
else if (nextmove == DESTMOVE) {
11873 eprevesymself(*searchtet);
11875 esymself(*searchtet);
11879 if (issubface(*searchtet)) {
11885 fsymself(*searchtet);
11886 if (oppo(*searchtet) == dummypoint) {
11892 torg = org(*searchtet);
11893 tdest = dest(*searchtet);
11894 tapex = apex(*searchtet);
11910 void tetgenmesh::flippush(badface*& fstack, triface* flipface)
11912 if (!facemarked(*flipface)) {
11913 badface *newflipface = (badface *) flippool->alloc();
11914 newflipface->tt = *flipface;
11915 markface(newflipface->tt);
11917 newflipface->nextitem = fstack;
11918 fstack = newflipface;
11941 int tetgenmesh::incrementalflip(point newpt,
int hullflag, flipconstraints *fc)
11944 triface fliptets[5], *parytet;
11945 point *pts, *parypt, pe;
11951 if (b->verbose > 2) {
11952 printf(
" Lawson flip (%ld faces).\n", flippool->items);
11958 popface = flipstack;
11959 while (popface != NULL) {
11960 pts = (point *) popface->tt.tet;
11961 for (i = 4; i < 8; i++) {
11962 if ((pts[i] != newpt) && (pts[i] != dummypoint)) {
11963 if (!pinfected(pts[i])) {
11965 cavetetvertlist->newindex((
void **) &parypt);
11970 popface = popface->nextitem;
11975 while (flipstack != NULL) {
11978 popface = flipstack;
11979 fliptets[0] = popface->tt;
11980 flipstack = flipstack->nextitem;
11981 flippool->dealloc((
void *) popface);
11984 if (isdeadtet(fliptets[0]))
continue;
11986 if (!facemarked(fliptets[0]))
continue;
11988 unmarkface(fliptets[0]);
11990 if ((point) fliptets[0].tet[7] == dummypoint) {
11992 fliptets[0].ver = epivot[fliptets[0].ver];
11994 fsym(fliptets[0], fliptets[1]);
11995 pts = (point *) fliptets[1].tet;
11996 ori = orient3d(pts[4], pts[5], pts[6], newpt);
12001 enext(fliptets[1], fliptets[2]);
12002 eprev(fliptets[1], fliptets[3]);
12003 fnextself(fliptets[2]);
12004 fnextself(fliptets[3]);
12005 if (oppo(fliptets[2]) == newpt) {
12006 if (oppo(fliptets[3]) == newpt) {
12008 terminatetetgen(
this, 2);
12010 esym(fliptets[2], fliptets[0]);
12011 fnext(fliptets[0], fliptets[1]);
12012 fnext(fliptets[1], fliptets[2]);
12019 flip32(fliptets, 1, fc);
12022 if (oppo(fliptets[3]) == newpt) {
12023 fnext(fliptets[3], fliptets[0]);
12024 fnext(fliptets[0], fliptets[1]);
12025 fnext(fliptets[1], fliptets[2]);
12030 flip32(fliptets, 1, fc);
12034 pe = oppo(fliptets[1]);
12035 if (!pinfected(pe)) {
12037 cavetetvertlist->newindex((
void **) &parypt);
12040 flip23(fliptets, 1, fc);
12049 flip23(fliptets, 1, fc);
12058 fsym(fliptets[0], fliptets[1]);
12059 if ((point) fliptets[1].tet[7] == dummypoint) {
12064 if (marktested(fliptets[1])) {
12070 pts = (point *) fliptets[1].tet;
12072 sign = orient4d_s(pts[4], pts[5], pts[6], pts[7], newpt,
12073 pts[4][3], pts[5][3], pts[6][3], pts[7][3],
12076 sign = insphere_s(pts[4], pts[5], pts[6], pts[7], newpt);
12082 point pe = oppo(fliptets[1]);
12086 for (i = 0; i < 3; i++) {
12087 ori = orient3d(org(fliptets[0]), dest(fliptets[0]), pd, pe);
12088 if (ori <= 0)
break;
12089 enextself(fliptets[0]);
12095 flip23(fliptets, 0, fc);
12101 esymself(fliptets[0]);
12102 for (i = 0; i < 3; i++) {
12103 fnext(fliptets[i], fliptets[i+1]);
12105 if (fliptets[3].tet == fliptets[0].tet) {
12107 flip32(fliptets, 0, fc);
12111 fnext(fliptets[3], fliptets[4]);
12112 if (fliptets[4].tet == fliptets[0].tet) {
12120 esymself(fliptets[0]);
12124 flip23(fliptets, 0, fc);
12125 fnext(fliptets[3], fliptets[1]);
12126 fnext(fliptets[1], fliptets[2]);
12134 flip32(&(fliptets[1]), (apex(fliptets[3]) == dummypoint), fc);
12142 marktest(fliptets[1]);
12144 cavebdrylist->newindex((
void **) &parytet);
12145 *parytet = fliptets[1];
12151 for (i = 0; i < cavebdrylist->objects; i++) {
12152 parytet = (triface *) fastlookup(cavebdrylist, i);
12153 unmarktest(*parytet);
12155 cavebdrylist->restart();
12159 for (i = 0; i < cavetetvertlist->objects; i++) {
12160 parypt = (point *) fastlookup(cavetetvertlist, i);
12161 puninfect(*parypt);
12163 cavetetvertlist->restart();
12179 void tetgenmesh::initialdelaunay(point pa, point pb, point pc, point pd)
12181 triface firsttet, tetopa, tetopb, tetopc, tetopd;
12182 triface worktet, worktet1;
12184 if (b->verbose > 2) {
12185 printf(
" Create init tet (%d, %d, %d, %d)\n", pointmark(pa),
12186 pointmark(pb), pointmark(pc), pointmark(pd));
12190 maketetrahedron(&firsttet);
12191 setvertices(firsttet, pa, pb, pc, pd);
12193 maketetrahedron(&tetopa);
12194 setvertices(tetopa, pb, pc, pd, dummypoint);
12195 maketetrahedron(&tetopb);
12196 setvertices(tetopb, pc, pa, pd, dummypoint);
12197 maketetrahedron(&tetopc);
12198 setvertices(tetopc, pa, pb, pd, dummypoint);
12199 maketetrahedron(&tetopd);
12200 setvertices(tetopd, pb, pa, pc, dummypoint);
12204 bond(firsttet, tetopd);
12205 esym(firsttet, worktet);
12206 bond(worktet, tetopc);
12207 enextesym(firsttet, worktet);
12208 bond(worktet, tetopa);
12209 eprevesym(firsttet, worktet);
12210 bond(worktet, tetopb);
12213 esym(tetopc, worktet);
12214 esym(tetopd, worktet1);
12215 bond(worktet, worktet1);
12216 esym(tetopa, worktet);
12217 eprevesym(tetopd, worktet1);
12218 bond(worktet, worktet1);
12219 esym(tetopb, worktet);
12220 enextesym(tetopd, worktet1);
12221 bond(worktet, worktet1);
12222 eprevesym(tetopc, worktet);
12223 enextesym(tetopb, worktet1);
12224 bond(worktet, worktet1);
12225 eprevesym(tetopa, worktet);
12226 enextesym(tetopc, worktet1);
12227 bond(worktet, worktet1);
12228 eprevesym(tetopb, worktet);
12229 enextesym(tetopa, worktet1);
12230 bond(worktet, worktet1);
12233 if (pointtype(pa) == UNUSEDVERTEX) {
12234 setpointtype(pa, VOLVERTEX);
12236 if (pointtype(pb) == UNUSEDVERTEX) {
12237 setpointtype(pb, VOLVERTEX);
12239 if (pointtype(pc) == UNUSEDVERTEX) {
12240 setpointtype(pc, VOLVERTEX);
12242 if (pointtype(pd) == UNUSEDVERTEX) {
12243 setpointtype(pd, VOLVERTEX);
12246 setpoint2tet(pa, encode(firsttet));
12247 setpoint2tet(pb, encode(firsttet));
12248 setpoint2tet(pc, encode(firsttet));
12249 setpoint2tet(pd, encode(firsttet));
12252 recenttet = firsttet;
12263 void tetgenmesh::incrementaldelaunay(clock_t& tv)
12266 point *permutarray, swapvertex;
12267 REAL v1[3], v2[3], n[3];
12268 REAL bboxsize, bboxsize2, bboxsize3, ori;
12274 printf(
"Delaunizing vertices...\n");
12278 permutarray =
new point[in->numberofpoints];
12279 points->traversalinit();
12283 printf(
" Using the input order.\n");
12285 for (i = 0; i < in->numberofpoints; i++) {
12286 permutarray[i] = (point) points->traverse();
12290 printf(
" Permuting vertices.\n");
12292 srand(in->numberofpoints);
12293 for (i = 0; i < in->numberofpoints; i++) {
12294 randindex = rand() % (i + 1);
12295 permutarray[i] = permutarray[randindex];
12296 permutarray[randindex] = (point) points->traverse();
12298 if (b->brio_hilbert) {
12300 printf(
" Sorting vertices.\n");
12302 hilbert_init(in->mesh_dim);
12303 brio_multiscale_sort(permutarray, in->numberofpoints, b->brio_threshold,
12304 b->brio_ratio, &ngroup);
12311 bboxsize = sqrt(norm2(xmax - xmin, ymax - ymin, zmax - zmin));
12312 bboxsize2 = bboxsize * bboxsize;
12313 bboxsize3 = bboxsize2 * bboxsize;
12317 while ((distance(permutarray[0],permutarray[i])/bboxsize)<b->epsilon) {
12319 if (i == in->numberofpoints - 1) {
12320 printf(
"Exception: All vertices are (nearly) identical (Tol = %g).\n",
12322 terminatetetgen(
this, 10);
12327 swapvertex = permutarray[i];
12328 permutarray[i] = permutarray[1];
12329 permutarray[1] = swapvertex;
12336 for (j = 0; j < 3; j++) {
12337 v1[j] = permutarray[1][j] - permutarray[0][j];
12338 v2[j] = permutarray[i][j] - permutarray[0][j];
12341 while ((sqrt(norm2(n[0], n[1], n[2])) / bboxsize2) < b->epsilon) {
12343 if (i == in->numberofpoints - 1) {
12344 printf(
"Exception: All vertices are (nearly) collinear (Tol = %g).\n",
12346 terminatetetgen(
this, 10);
12348 for (j = 0; j < 3; j++) {
12349 v2[j] = permutarray[i][j] - permutarray[0][j];
12355 swapvertex = permutarray[i];
12356 permutarray[i] = permutarray[2];
12357 permutarray[2] = swapvertex;
12362 ori = orient3dfast(permutarray[0], permutarray[1], permutarray[2],
12364 while ((fabs(ori) / bboxsize3) < b->epsilon) {
12366 if (i == in->numberofpoints) {
12367 printf(
"Exception: All vertices are coplanar (Tol = %g).\n",
12369 terminatetetgen(
this, 10);
12371 ori = orient3dfast(permutarray[0], permutarray[1], permutarray[2],
12376 swapvertex = permutarray[i];
12377 permutarray[i] = permutarray[3];
12378 permutarray[3] = swapvertex;
12385 swapvertex = permutarray[0];
12386 permutarray[0] = permutarray[1];
12387 permutarray[1] = swapvertex;
12391 initialdelaunay(permutarray[0], permutarray[1], permutarray[2],
12395 printf(
" Incrementally inserting vertices.\n");
12397 insertvertexflags ivf;
12398 flipconstraints fc;
12411 for (i = 4; i < in->numberofpoints; i++) {
12412 if (pointtype(permutarray[i]) == UNUSEDVERTEX) {
12413 setpointtype(permutarray[i], VOLVERTEX);
12415 if (b->brio_hilbert || b->no_sort) {
12417 searchtet.tet = recenttet.tet;
12420 searchtet.tet = NULL;
12422 ivf.iloc = (int) OUTSIDE;
12424 if (insertpoint(permutarray[i], &searchtet, NULL, NULL, &ivf)) {
12425 if (flipstack != NULL) {
12427 incrementalflip(permutarray[i], (ivf.iloc == (
int) OUTSIDE), &fc);
12430 if (ivf.iloc == (
int) ONVERTEX) {
12432 swapvertex = org(searchtet);
12433 if (b->object != tetgenbehavior::STL) {
12435 printf(
"Warning: Point #%d is coincident with #%d. Ignored!\n",
12436 pointmark(permutarray[i]), pointmark(swapvertex));
12439 setpoint2ppt(permutarray[i], swapvertex);
12440 setpointtype(permutarray[i], DUPLICATEDVERTEX);
12442 }
else if (ivf.iloc == (
int) NEARVERTEX) {
12443 swapvertex = org(searchtet);
12445 printf(
"Warning: Point %d is replaced by point %d.\n",
12446 pointmark(permutarray[i]), pointmark(swapvertex));
12447 printf(
" Avoid creating a very short edge (len = %g) (< %g).\n",
12448 permutarray[i][3], minedgelength);
12449 printf(
" You may try a smaller tolerance (-T) (current is %g)\n",
12451 printf(
" or use the option -M0/1 to avoid such replacement.\n");
12454 setpoint2ppt(permutarray[i], swapvertex);
12455 setpointtype(permutarray[i], DUPLICATEDVERTEX);
12457 }
else if (ivf.iloc == (
int) NONREGULAR) {
12460 printf(
" Point #%d is non-regular, skipped.\n",
12461 pointmark(permutarray[i]));
12463 setpointtype(permutarray[i], NREGULARVERTEX);
12471 delete [] permutarray;
12488 void tetgenmesh::flipshpush(face* flipedge)
12490 badface *newflipface;
12492 newflipface = (badface *) flippool->alloc();
12493 newflipface->ss = *flipedge;
12494 newflipface->forg = sorg(*flipedge);
12495 newflipface->fdest = sdest(*flipedge);
12496 newflipface->nextitem = flipstack;
12497 flipstack = newflipface;
12510 void tetgenmesh::flip22(face* flipfaces,
int flipflag,
int chkencflag)
12512 face bdedges[4], outfaces[4], infaces[4];
12515 point pa, pb, pc, pd;
12518 pa = sorg(flipfaces[0]);
12519 pb = sdest(flipfaces[0]);
12520 pc = sapex(flipfaces[0]);
12521 pd = sapex(flipfaces[1]);
12523 if (sorg(flipfaces[1]) != pb) {
12524 sesymself(flipfaces[1]);
12530 senext(flipfaces[0], bdedges[0]);
12531 senext2(flipfaces[0], bdedges[1]);
12532 senext(flipfaces[1], bdedges[2]);
12533 senext2(flipfaces[1], bdedges[3]);
12536 for (i = 0; i < 4; i++) {
12537 spivot(bdedges[i], outfaces[i]);
12538 infaces[i] = outfaces[i];
12539 sspivot(bdedges[i], bdsegs[i]);
12540 if (outfaces[i].sh != NULL) {
12541 if (isshsubseg(bdedges[i])) {
12542 spivot(infaces[i], checkface);
12543 while (checkface.sh != bdedges[i].sh) {
12544 infaces[i] = checkface;
12545 spivot(infaces[i], checkface);
12556 setshvertices(flipfaces[0], pc, pd, pb);
12558 setshvertices(flipfaces[1], pd, pc, pa);
12561 if (pointtype(pa) == FREEFACETVERTEX) {
12562 setpoint2sh(pa, sencode(flipfaces[1]));
12564 if (pointtype(pb) == FREEFACETVERTEX) {
12565 setpoint2sh(pb, sencode(flipfaces[0]));
12567 if (pointtype(pc) == FREEFACETVERTEX) {
12568 setpoint2sh(pc, sencode(flipfaces[0]));
12570 if (pointtype(pd) == FREEFACETVERTEX) {
12571 setpoint2sh(pd, sencode(flipfaces[0]));
12575 for (i = 0; i < 4; i++) {
12576 if (outfaces[(3 + i) % 4].sh != NULL) {
12578 if (bdsegs[(3 + i) % 4].sh != NULL) {
12579 bdsegs[(3 + i) % 4].shver = 0;
12580 if (sorg(bdedges[i]) != sorg(bdsegs[(3 + i) % 4])) {
12581 sesymself(bdedges[i]);
12584 sbond1(bdedges[i], outfaces[(3 + i) % 4]);
12585 sbond1(infaces[(3 + i) % 4], bdedges[i]);
12587 sdissolve(bdedges[i]);
12589 if (bdsegs[(3 + i) % 4].sh != NULL) {
12590 ssbond(bdedges[i], bdsegs[(3 + i) % 4]);
12591 if (chkencflag & 1) {
12593 enqueuesubface(badsubsegs, &(bdsegs[(3 + i) % 4]));
12596 ssdissolve(bdedges[i]);
12600 if (chkencflag & 2) {
12602 for (i = 0; i < 2; i++) {
12603 enqueuesubface(badsubfacs, &(flipfaces[i]));
12607 recentsh = flipfaces[0];
12611 for (i = 0; i < 4; i++) {
12612 flipshpush(&(bdedges[i]));
12632 void tetgenmesh::flip31(face* flipfaces,
int flipflag)
12634 face bdedges[3], outfaces[3], infaces[3];
12640 pa = sdest(flipfaces[0]);
12641 pb = sdest(flipfaces[1]);
12642 pc = sdest(flipfaces[2]);
12647 for (i = 0; i < 3; i++) {
12648 senext(flipfaces[i], bdedges[i]);
12649 spivot(bdedges[i], outfaces[i]);
12650 infaces[i] = outfaces[i];
12651 sspivot(bdedges[i], bdsegs[i]);
12652 if (outfaces[i].sh != NULL) {
12653 if (isshsubseg(bdedges[i])) {
12654 spivot(infaces[i], checkface);
12655 while (checkface.sh != bdedges[i].sh) {
12656 infaces[i] = checkface;
12657 spivot(infaces[i], checkface);
12664 makeshellface(subfaces, &(flipfaces[3]));
12665 setshvertices(flipfaces[3], pa, pb,pc);
12666 setshellmark(flipfaces[3], shellmark(flipfaces[0]));
12667 if (checkconstraints) {
12669 setareabound(flipfaces[3], areabound(flipfaces[0]));
12671 if (useinsertradius) {
12672 setfacetindex(flipfaces[3], getfacetindex(flipfaces[0]));
12676 if (pointtype(pa) == FREEFACETVERTEX) {
12677 setpoint2sh(pa, sencode(flipfaces[3]));
12679 if (pointtype(pb) == FREEFACETVERTEX) {
12680 setpoint2sh(pb, sencode(flipfaces[3]));
12682 if (pointtype(pc) == FREEFACETVERTEX) {
12683 setpoint2sh(pc, sencode(flipfaces[3]));
12687 bdedges[0] = flipfaces[3];
12688 senext(flipfaces[3], bdedges[1]);
12689 senext2(flipfaces[3], bdedges[2]);
12692 for (i = 0; i < 3; i++) {
12693 if (outfaces[i].sh != NULL) {
12695 if (bdsegs[i].sh != NULL) {
12696 bdsegs[i].shver = 0;
12697 if (sorg(bdedges[i]) != sorg(bdsegs[i])) {
12698 sesymself(bdedges[i]);
12701 sbond1(bdedges[i], outfaces[i]);
12702 sbond1(infaces[i], bdedges[i]);
12704 if (bdsegs[i].sh != NULL) {
12705 ssbond(bdedges[i], bdsegs[i]);
12709 recentsh = flipfaces[3];
12713 for (i = 0; i < 3; i++) {
12714 flipshpush(&(bdedges[i]));
12725 long tetgenmesh::lawsonflip()
12729 point pa, pb, pc, pd;
12731 long flipcount = 0;
12733 if (b->verbose > 2) {
12734 printf(
" Lawson flip %ld edges.\n", flippool->items);
12737 while (flipstack != (badface *) NULL) {
12740 popface = flipstack;
12741 flipfaces[0] = popface->ss;
12742 pa = popface->forg;
12743 pb = popface->fdest;
12744 flipstack = popface->nextitem;
12745 flippool->dealloc((
void *) popface);
12748 if (flipfaces[0].sh[3] == NULL)
continue;
12750 if ((sorg(flipfaces[0]) != pa) || (sdest(flipfaces[0]) != pb))
continue;
12752 if (isshsubseg(flipfaces[0]))
continue;
12755 spivot(flipfaces[0], flipfaces[1]);
12756 if (flipfaces[1].sh == NULL)
continue;
12757 pc = sapex(flipfaces[0]);
12758 pd = sapex(flipfaces[1]);
12760 sign = incircle3d(pa, pb, pc, pd);
12764 flip22(flipfaces, 1, 0);
12769 if (b->verbose > 2) {
12770 printf(
" Performed %ld flips.\n", flipcount);
12807 int tetgenmesh::sinsertvertex(point insertpt, face *searchsh, face *splitseg,
12808 int iloc,
int bowywat,
int rflag)
12810 face cavesh, neighsh, *parysh;
12811 face newsh, casout, casin;
12814 enum locateresult loc = OUTSIDE;
12818 if (b->verbose > 2) {
12819 printf(
" Insert facet point %d.\n", pointmark(insertpt));
12822 if (bowywat == 3) {
12826 if ((splitseg != NULL) && (splitseg->sh != NULL)) {
12828 spivot(*splitseg, *searchsh);
12829 if (loc != INSTAR) loc = ONEDGE;
12831 if (loc != INSTAR) loc = (
enum locateresult) iloc;
12832 if (loc == OUTSIDE) {
12834 if (searchsh->sh == NULL) {
12835 *searchsh = recentsh;
12838 loc = slocate(insertpt, searchsh, 1, 1, rflag);
12844 if (loc == ONFACE) {
12846 smarktest(*searchsh);
12847 caveshlist->newindex((
void **) &parysh);
12848 *parysh = *searchsh;
12849 }
else if (loc == ONEDGE) {
12850 if ((splitseg != NULL) && (splitseg->sh != NULL)) {
12851 splitseg->shver = 0;
12852 pa = sorg(*splitseg);
12854 pa = sorg(*searchsh);
12856 if (searchsh->sh != NULL) {
12858 neighsh = *searchsh;
12861 if (sorg(neighsh) != pa) sesymself(neighsh);
12863 smarktest(neighsh);
12864 caveshlist->newindex((
void **) &parysh);
12867 cavesegshlist->newindex((
void **) &parysh);
12870 spivotself(neighsh);
12872 if (neighsh.sh == searchsh->sh)
break;
12873 if (neighsh.sh == NULL)
break;
12876 }
else if (loc == ONVERTEX) {
12878 }
else if (loc == OUTSIDE) {
12886 neighsh = *searchsh;
12888 senext2self(neighsh);
12889 spivot(neighsh, casout);
12890 if (casout.sh == NULL) {
12892 ori = orient3d(sorg(neighsh), sdest(neighsh), dummypoint, insertpt);
12894 *searchsh = neighsh;
12899 if (sorg(casout) != sdest(neighsh)) sesymself(casout);
12905 pa = sorg(*searchsh);
12906 pb = sdest(*searchsh);
12909 makeshellface(subfaces, &newsh);
12910 setshvertices(newsh, pb, pa, insertpt);
12911 setshellmark(newsh, shellmark(*searchsh));
12912 if (checkconstraints) {
12914 setareabound(newsh, areabound(*searchsh));
12916 if (useinsertradius) {
12917 setfacetindex(newsh, getfacetindex(*searchsh));
12920 sbond1(newsh, *searchsh);
12921 sbond1(*searchsh, newsh);
12923 if (casin.sh != NULL) {
12924 senext(newsh, casout);
12925 sbond1(casout, casin);
12926 sbond1(casin, casout);
12929 senext2(newsh, casin);
12932 caveshlist->newindex((
void **) &parysh);
12935 neighsh = *searchsh;
12937 senextself(neighsh);
12938 spivot(neighsh, casout);
12939 if (casout.sh == NULL) {
12940 *searchsh = neighsh;
12943 if (sorg(casout) != sdest(neighsh)) sesymself(casout);
12947 pa = sorg(*searchsh);
12948 pb = sdest(*searchsh);
12949 ori = orient3d(pa, pb, dummypoint, insertpt);
12951 if (ori >= 0)
break;
12953 }
else if (loc == INSTAR) {
12959 for (i = 0; i < caveshlist->objects; i++) {
12960 cavesh = * (face *) fastlookup(caveshlist, i);
12961 for (j = 0; j < 3; j++) {
12962 if (!isshsubseg(cavesh)) {
12963 spivot(cavesh, neighsh);
12964 if (neighsh.sh != NULL) {
12966 if (!smarktested(neighsh)) {
12968 if (loc == INSTAR) {
12973 if (!isshtet(neighsh)) {
12975 sign = incircle3d(sorg(neighsh), sdest(neighsh),
12976 sapex(neighsh), insertpt);
12984 smarktest(neighsh);
12985 caveshlist->newindex((
void **) &parysh);
12996 if (loc == OUTSIDE) {
12998 if ((sorg(cavesh) == insertpt) || (sdest(cavesh) == insertpt)) {
13013 caveshbdlist->newindex((
void **) &parysh);
13016 senextself(cavesh);
13022 for (i = 0; i < caveshbdlist->objects; i++) {
13023 parysh = (face *) fastlookup(caveshbdlist, i);
13024 sspivot(*parysh, checkseg);
13025 if ((parysh->shver & 01) != 0) sesymself(*parysh);
13026 pa = sorg(*parysh);
13027 pb = sdest(*parysh);
13029 makeshellface(subfaces, &newsh);
13030 setshvertices(newsh, pa, pb, insertpt);
13031 setshellmark(newsh, shellmark(*parysh));
13032 if (checkconstraints) {
13034 setareabound(newsh, areabound(*parysh));
13036 if (useinsertradius) {
13037 setfacetindex(newsh, getfacetindex(*parysh));
13040 if (pointtype(pa) == FREEFACETVERTEX) {
13041 setpoint2sh(pa, sencode(newsh));
13043 if (pointtype(pb) == FREEFACETVERTEX) {
13044 setpoint2sh(pb, sencode(newsh));
13047 spivot(*parysh, casout);
13048 if (casout.sh != NULL) {
13050 if (checkseg.sh != NULL) {
13052 checkseg.shver = 0;
13053 if (sorg(newsh) != sorg(checkseg)) {
13055 sesymself(*parysh);
13057 spivot(casin, neighsh);
13058 while (neighsh.sh != parysh->sh) {
13060 spivot(casin, neighsh);
13063 sbond1(newsh, casout);
13064 sbond1(casin, newsh);
13066 if (checkseg.sh != NULL) {
13067 ssbond(newsh, checkseg);
13071 sbond1(*parysh, newsh);
13074 if (newsh.sh != NULL) {
13080 if (pointtype(insertpt) == FREEFACETVERTEX) {
13081 setpoint2sh(insertpt, sencode(newsh));
13085 for (i = 0; i < caveshbdlist->objects; i++) {
13087 parysh = (face *) fastlookup(caveshbdlist, i);
13088 spivot(*parysh, newsh);
13090 spivot(newsh, neighsh);
13091 if (neighsh.sh == NULL) {
13093 pb = sdest(*parysh);
13096 senextself(neighsh);
13097 spivotself(neighsh);
13098 if (neighsh.sh == NULL)
break;
13099 if (!smarktested(neighsh))
break;
13100 if (sdest(neighsh) != pb) sesymself(neighsh);
13102 if (neighsh.sh != NULL) {
13104 if (sorg(neighsh) != pb) sesymself(neighsh);
13105 senext2self(neighsh);
13106 sbond(newsh, neighsh);
13109 spivot(*parysh, newsh);
13110 senext2self(newsh);
13111 spivot(newsh, neighsh);
13112 if (neighsh.sh == NULL) {
13114 pa = sorg(*parysh);
13117 senext2self(neighsh);
13118 spivotself(neighsh);
13119 if (neighsh.sh == NULL)
break;
13120 if (!smarktested(neighsh))
break;
13121 if (sorg(neighsh) != pa) sesymself(neighsh);
13123 if (neighsh.sh != NULL) {
13125 if (sdest(neighsh) != pa) sesymself(neighsh);
13126 senextself(neighsh);
13127 sbond(newsh, neighsh);
13132 if ((loc == ONEDGE) || ((splitseg != NULL) && (splitseg->sh != NULL))
13133 || (cavesegshlist->objects > 0l)) {
13139 face aseg, bseg, aoutseg, boutseg;
13141 for (i = 0; i < cavesegshlist->objects; i++) {
13143 parysh = (face *) fastlookup(cavesegshlist, i);
13145 spivot(*parysh, cavesh);
13146 if (sapex(cavesh) == insertpt) {
13148 if (cavesegshlist->objects > 1) {
13150 j = (i + 1) % (
int) cavesegshlist->objects;
13151 parysh = (face *) fastlookup(cavesegshlist, j);
13152 spivot(*parysh, neighsh);
13154 if (sorg(neighsh) != sorg(cavesh)) {
13155 sesymself(neighsh);
13162 for (j = 0; j < 2; j++) {
13163 senextself(cavesh);
13164 senextself(neighsh);
13165 spivot(cavesh, newsh);
13166 spivot(neighsh, casout);
13167 sbond1(newsh, casout);
13174 for (j = 0; j < 2; j++) {
13175 senextself(cavesh);
13176 spivot(cavesh, newsh);
13182 if (pointtype(insertpt) == FREEFACETVERTEX) {
13183 setpoint2sh(insertpt, sencode(newsh));
13188 if ((splitseg != NULL) && (splitseg->sh != NULL)) {
13189 if (loc != INSTAR) {
13190 smarktest(*splitseg);
13194 pa = sorg(*splitseg);
13195 pb = sdest(*splitseg);
13198 makeshellface(subsegs, &aseg);
13199 makeshellface(subsegs, &bseg);
13201 setshvertices(aseg, pa, insertpt, NULL);
13202 setshvertices(bseg, insertpt, pb, NULL);
13203 setshellmark(aseg, shellmark(*splitseg));
13204 setshellmark(bseg, shellmark(*splitseg));
13205 if (checkconstraints) {
13206 setareabound(aseg, areabound(*splitseg));
13207 setareabound(bseg, areabound(*splitseg));
13209 if (useinsertradius) {
13210 setfacetindex(aseg, getfacetindex(*splitseg));
13211 setfacetindex(bseg, getfacetindex(*splitseg));
13215 senext2(*splitseg, boutseg);
13216 spivotself(boutseg);
13217 if (boutseg.sh != NULL) {
13218 senext2(aseg, aoutseg);
13219 sbond(boutseg, aoutseg);
13222 senext(*splitseg, aoutseg);
13223 spivotself(aoutseg);
13224 if (aoutseg.sh != NULL) {
13225 senext(bseg, boutseg);
13226 sbond(boutseg, aoutseg);
13229 senext(aseg, aoutseg);
13230 senext2(bseg, boutseg);
13231 sbond(aoutseg, boutseg);
13236 for (i = 0; i < cavesegshlist->objects; i++) {
13237 parysh = (face *) fastlookup(cavesegshlist, i);
13238 spivot(*parysh, neighsh);
13240 if (sorg(neighsh) != pa) {
13241 sesymself(neighsh);
13243 senext2(neighsh, newsh);
13245 ssbond(newsh, aseg);
13246 senext(neighsh, newsh);
13248 ssbond(newsh, bseg);
13253 if (pointtype(insertpt) == FREESEGVERTEX) {
13254 setpoint2sh(insertpt, sencode(aseg));
13257 if (pointtype(pa) == FREESEGVERTEX) {
13258 setpoint2sh(pa, sencode(aseg));
13260 if (pointtype(pb) == FREESEGVERTEX) {
13261 setpoint2sh(pb, sencode(bseg));
13266 for (i = 0; i < cavesegshlist->objects; i++) {
13267 parysh = (face *) fastlookup(cavesegshlist, i);
13268 spivotself(*parysh);
13269 if (sapex(*parysh) == insertpt) {
13270 shellfacedealloc(subfaces, parysh->sh);
13273 cavesegshlist->restart();
13275 if ((splitseg != NULL) && (splitseg->sh != NULL)) {
13278 cavesegshlist->newindex((
void **) &parysh);
13280 cavesegshlist->newindex((
void **) &parysh);
13308 int tetgenmesh::sremovevertex(point delpt, face* parentsh, face* parentseg,
13311 face flipfaces[4], spinsh, *parysh;
13312 point pa, pb, pc, pd;
13316 if (parentseg != NULL) {
13319 face startsh, neighsh, nextsh;
13320 face abseg, prevseg, checkseg;
13321 face adjseg1, adjseg2;
13323 senext2(*parentseg, prevseg);
13324 spivotself(prevseg);
13327 pa = sorg(prevseg);
13328 pb = sdest(*parentseg);
13329 if (b->verbose > 2) {
13330 printf(
" Remove vertex %d from segment [%d, %d].\n",
13331 pointmark(delpt), pointmark(pa), pointmark(pb));
13333 makeshellface(subsegs, &abseg);
13334 setshvertices(abseg, pa, pb, NULL);
13335 setshellmark(abseg, shellmark(*parentseg));
13336 if (checkconstraints) {
13337 setareabound(abseg, areabound(*parentseg));
13339 if (useinsertradius) {
13340 setfacetindex(abseg, getfacetindex(*parentseg));
13343 senext2(prevseg, adjseg1);
13344 spivotself(adjseg1);
13345 if (adjseg1.sh != NULL) {
13347 senextself(adjseg1);
13348 senext2(abseg, adjseg2);
13349 sbond(adjseg1, adjseg2);
13352 senext(*parentseg, adjseg1);
13353 spivotself(adjseg1);
13354 if (adjseg1.sh != NULL) {
13356 senext2self(adjseg1);
13357 senext(abseg, adjseg2);
13358 sbond(adjseg1, adjseg2);
13361 setpoint2sh(pa, sencode(abseg));
13362 setpoint2sh(pb, sencode(abseg));
13366 spivot(*parentseg, *parentsh);
13367 if (parentsh->sh != NULL) {
13368 spinsh = *parentsh;
13371 caveshlist->newindex((
void **) &parysh);
13374 spivotself(spinsh);
13375 if (spinsh.sh == NULL) {
13378 if (spinsh.sh == parentsh->sh)
break;
13384 for (i = 0; i < caveshlist->objects; i++) {
13385 parysh = (face *) fastlookup(caveshlist, i);
13387 if (sorg(startsh) != delpt) {
13388 sesymself(startsh);
13393 senext2self(neighsh);
13394 sspivot(neighsh, checkseg);
13395 if (checkseg.sh != NULL) {
13399 spivotself(neighsh);
13400 if (sorg(neighsh) != delpt) sesymself(neighsh);
13403 if (neighsh.sh != startsh.sh) {
13405 ssdissolve(startsh);
13406 ssdissolve(neighsh);
13410 makeshellface(subfaces, &fakesh);
13411 setshvertices(fakesh, pa, pb, delpt);
13412 setshellmark(fakesh, shellmark(startsh));
13414 ssbond(fakesh, abseg);
13416 senext(fakesh, nextsh);
13417 sbond(nextsh, startsh);
13418 senext2(fakesh, nextsh);
13419 sbond(nextsh, neighsh);
13424 senext2self(neighsh);
13427 spivot(neighsh, startsh);
13428 if (sorg(startsh) != pa) sesymself(startsh);
13429 sdissolve(startsh);
13431 ssbond(startsh, abseg);
13434 shellfacedealloc(subfaces, neighsh.sh);
13437 cavesegshlist->newindex((
void **) &parysh);
13440 caveshlist->restart();
13443 if (cavesegshlist->objects > 1) {
13444 for (i = 0; i < cavesegshlist->objects; i++) {
13445 parysh = (face *) fastlookup(cavesegshlist, i);
13448 j = (i + 1) % cavesegshlist->objects;
13449 parysh = (face *) fastlookup(cavesegshlist, j);
13451 sbond1(fakesh, nextsh);
13456 shellfacedealloc(subsegs, parentseg->sh);
13457 shellfacedealloc(subsegs, prevseg.sh);
13459 *parentseg = abseg;
13462 if (b->verbose > 2) {
13463 printf(
" Remove vertex %d from surface.\n", pointmark(delpt));
13466 senextself(*parentsh);
13468 cavesegshlist->newindex((
void **) &parysh);
13469 *parysh = *parentsh;
13474 for (it = 0; it < cavesegshlist->objects; it++) {
13475 parentsh = (face *) fastlookup(cavesegshlist, it);
13476 senextself(*parentsh);
13477 spivotself(*parentsh);
13478 if (sorg(*parentsh) != delpt) sesymself(*parentsh);
13480 if (sorg(*parentsh) != delpt) {
13487 spinsh = *parentsh;
13489 caveshlist->newindex((
void **) &parysh);
13491 senext2self(spinsh);
13492 spivotself(spinsh);
13493 if (spinsh.sh == parentsh->sh)
break;
13494 if (sorg(spinsh) != delpt) sesymself(spinsh);
13497 if (caveshlist->objects == 3) {
13499 for (i = 0; i < 3; i++) {
13500 parysh = (face *) fastlookup(caveshlist, i);
13501 flipfaces[i] = *parysh;
13503 flip31(flipfaces, lawson);
13504 for (i = 0; i < 3; i++) {
13505 shellfacedealloc(subfaces, flipfaces[i].sh);
13507 caveshlist->restart();
13509 caveshbdlist->newindex((
void **) &parysh);
13510 *parysh = flipfaces[3];
13516 for (i = 0; i < caveshlist->objects; i++) {
13517 parysh = (face *) fastlookup(caveshlist, i);
13518 flipfaces[0] = *parysh;
13519 spivot(flipfaces[0], flipfaces[1]);
13520 if (sorg(flipfaces[0]) != sdest(flipfaces[1]))
13521 sesymself(flipfaces[1]);
13523 if (!smarktested(flipfaces[0]) && !smarktested(flipfaces[1])) {
13524 pa = sorg(flipfaces[0]);
13525 pb = sdest(flipfaces[0]);
13526 pc = sapex(flipfaces[0]);
13527 pd = sapex(flipfaces[1]);
13528 calculateabovepoint4(pa, pb, pc, pd);
13530 ori1 = orient3d(pc, pd, dummypoint, pa);
13531 ori2 = orient3d(pc, pd, dummypoint, pb);
13532 if (ori1 * ori2 < 0) {
13534 flip22(flipfaces, lawson, 0);
13537 senext2(flipfaces[1], *parentsh);
13539 caveshbdlist->newindex((
void **) &parysh);
13540 *parysh = flipfaces[0];
13546 if (i == caveshlist->objects) {
13548 parysh = (face *) fastlookup(caveshlist, 0);
13549 flipfaces[0] = *parysh;
13550 spivot(flipfaces[0], flipfaces[1]);
13551 if (sorg(flipfaces[0]) != sdest(flipfaces[1])) {
13552 sesymself(flipfaces[1]);
13554 flip22(flipfaces, lawson, 0);
13555 senext2(flipfaces[1], *parentsh);
13557 caveshbdlist->newindex((
void **) &parysh);
13558 *parysh = flipfaces[0];
13562 caveshlist->restart();
13567 cavesegshlist->restart();
13569 if (b->verbose > 2) {
13570 printf(
" Created %ld new subfaces.\n", caveshbdlist->objects);
13608 enum tetgenmesh::locateresult tetgenmesh::slocate(point searchpt,
13609 face* searchsh,
int aflag,
int cflag,
int rflag)
13613 enum locateresult loc;
13614 enum {MOVE_BC, MOVE_CA} nextmove;
13615 REAL ori, ori_bc, ori_ca;
13618 pa = sorg(*searchsh);
13619 pb = sdest(*searchsh);
13620 pc = sapex(*searchsh);
13624 calculateabovepoint4(pa, pb, pc, searchpt);
13628 ori = orient3d(pa, pb, pc, dummypoint);
13630 sesymself(*searchsh);
13631 }
else if (ori == 0.0) {
13637 for (i = 0; i < 3; i++) {
13638 pa = sorg(*searchsh);
13639 pb = sdest(*searchsh);
13640 ori = orient3d(pa, pb, dummypoint, searchpt);
13641 if (ori > 0)
break;
13642 senextself(*searchsh);
13648 pc = sapex(*searchsh);
13650 if (pc == searchpt) {
13651 senext2self(*searchsh);
13657 ori_bc = orient3d(pb, pc, dummypoint, searchpt);
13658 ori_ca = orient3d(pc, pa, dummypoint, searchpt);
13663 if (randomnation(2)) {
13664 nextmove = MOVE_CA;
13666 nextmove = MOVE_BC;
13670 nextmove = MOVE_BC;
13675 nextmove = MOVE_CA;
13682 senext2self(*searchsh);
13688 senextself(*searchsh);
13693 senext2self(*searchsh);
13701 if (nextmove == MOVE_BC) {
13702 senextself(*searchsh);
13704 senext2self(*searchsh);
13708 if (isshsubseg(*searchsh)) {
13712 spivot(*searchsh, neighsh);
13713 if (neighsh.sh == NULL) {
13717 if (sorg(neighsh) != sdest(*searchsh)) {
13718 sesymself(neighsh);
13722 *searchsh = neighsh;
13723 pa = sorg(*searchsh);
13724 pb = sdest(*searchsh);
13725 pc = sapex(*searchsh);
13727 if (pc == searchpt) {
13728 senext2self(*searchsh);
13739 REAL n[3], area_abc, area_abp, area_bcp, area_cap;
13741 pa = sorg(*searchsh);
13742 pb = sdest(*searchsh);
13743 pc = sapex(*searchsh);
13745 facenormal(pa, pb, pc, n, 1, NULL);
13746 area_abc = sqrt(dot(n, n));
13748 facenormal(pb, pc, searchpt, n, 1, NULL);
13749 area_bcp = sqrt(dot(n, n));
13750 if ((area_bcp / area_abc) < b->epsilon) {
13754 facenormal(pc, pa, searchpt, n, 1, NULL);
13755 area_cap = sqrt(dot(n, n));
13756 if ((area_cap / area_abc) < b->epsilon) {
13760 if ((loc == ONFACE) || (loc == OUTSIDE)) {
13761 facenormal(pa, pb, searchpt, n, 1, NULL);
13762 area_abp = sqrt(dot(n, n));
13763 if ((area_abp / area_abc) < b->epsilon) {
13770 if (area_abp == 0) {
13771 if (area_bcp == 0) {
13772 senextself(*searchsh);
13775 if (area_cap == 0) {
13781 }
else if (area_bcp == 0) {
13782 if (area_cap == 0) {
13783 senext2self(*searchsh);
13786 senextself(*searchsh);
13789 }
else if (area_cap == 0) {
13790 senext2self(*searchsh);
13816 enum tetgenmesh::interresult tetgenmesh::sscoutsegment(face *searchsh,
13817 point endpt,
int insertsegflag,
int reporterrorflag,
int chkencflag)
13819 face flipshs[2], neighsh;
13820 point startpt, pa, pb, pc, pd;
13821 enum interresult dir;
13822 enum {MOVE_AB, MOVE_CA} nextmove;
13823 REAL ori_ab, ori_ca, len;
13827 startpt = sorg(*searchsh);
13828 nextmove = MOVE_AB;
13830 if (b->verbose > 2) {
13831 printf(
" Scout segment (%d, %d).\n", pointmark(startpt),
13834 len = distance(startpt, endpt);
13839 pb = sdest(*searchsh);
13845 pc = sapex(*searchsh);
13847 senext2self(*searchsh);
13848 sesymself(*searchsh);
13855 if ((sqrt(triarea(startpt, pb, endpt)) / len) < b->epsilon) {
13858 ori_ab = orient3d(startpt, pb, dummypoint, endpt);
13860 if ((sqrt(triarea(pc, startpt, endpt)) / len) < b->epsilon) {
13863 ori_ca = orient3d(pc, startpt, dummypoint, endpt);
13869 if (randomnation(2)) {
13870 nextmove = MOVE_CA;
13872 nextmove = MOVE_AB;
13875 nextmove = MOVE_AB;
13879 nextmove = MOVE_CA;
13888 senext2self(*searchsh);
13889 sesymself(*searchsh);
13900 terminatetetgen(
this, 2);
13907 if (nextmove == MOVE_AB) {
13910 if (isshsubseg(*searchsh)) {
13914 spivot(*searchsh, neighsh);
13915 if (neighsh.sh != NULL) {
13916 if (sorg(neighsh) != pb) sesymself(neighsh);
13917 senext(neighsh, *searchsh);
13921 senext2(*searchsh, neighsh);
13924 if (isshsubseg(neighsh)) {
13925 *searchsh = neighsh;
13929 spivotself(neighsh);
13930 if (sdest(neighsh) != pc) sesymself(neighsh);
13931 *searchsh = neighsh;
13934 senext2(*searchsh, neighsh);
13937 if (isshsubseg(neighsh)) {
13938 *searchsh = neighsh;
13942 spivotself(neighsh);
13943 if (neighsh.sh != NULL) {
13944 if (sdest(neighsh) != pc) sesymself(neighsh);
13945 *searchsh = neighsh;
13951 if (isshsubseg(*searchsh)) {
13955 spivot(*searchsh, neighsh);
13956 if (sorg(neighsh) != pb) sesymself(neighsh);
13957 senext(neighsh, *searchsh);
13962 if (dir == SHAREEDGE) {
13963 if (insertsegflag) {
13966 makeshellface(subsegs, &newseg);
13967 setshvertices(newseg, startpt, endpt, NULL);
13969 setshellmark(newseg, -1);
13970 ssbond(*searchsh, newseg);
13971 spivot(*searchsh, neighsh);
13972 if (neighsh.sh != NULL) {
13973 ssbond(neighsh, newseg);
13979 if (dir == ACROSSVERT) {
13981 if (reporterrorflag) {
13982 point pp = sdest(*searchsh);
13983 printf(
"PLC Error: A vertex lies in a segment in facet #%d.\n",
13984 shellmark(*searchsh));
13985 printf(
" Vertex: [%d] (%g,%g,%g).\n",pointmark(pp),pp[0],pp[1],pp[2]);
13986 printf(
" Segment: [%d, %d]\n", pointmark(startpt), pointmark(endpt));
13991 if (dir == ACROSSEDGE) {
13993 senext(*searchsh, flipshs[0]);
13994 if (isshsubseg(flipshs[0])) {
13995 if (reporterrorflag) {
13996 REAL P[3], Q[3], tp = 0, tq = 0;
13997 linelineint(startpt, endpt, pb, pc, P, Q, &tp, &tq);
13998 printf(
"PLC Error: Two segments intersect at point (%g,%g,%g),",
14000 printf(
" in facet #%d.\n", shellmark(*searchsh));
14001 printf(
" Segment 1: [%d, %d]\n", pointmark(pb), pointmark(pc));
14002 printf(
" Segment 2: [%d, %d]\n", pointmark(startpt),pointmark(endpt));
14007 spivot(flipshs[0], flipshs[1]);
14008 if (sorg(flipshs[1]) != sdest(flipshs[0])) sesymself(flipshs[1]);
14009 flip22(flipshs, 1, 0);
14011 pa = sapex(flipshs[1]);
14012 pb = sapex(flipshs[0]);
14013 pc = sorg(flipshs[0]);
14014 pd = sdest(flipshs[0]);
14017 ori_ab = orient3d(pc, pd, dummypoint, pb);
14018 ori_ca = orient3d(pd, pc, dummypoint, pa);
14020 flipshpush(&(flipshs[0]));
14021 }
else if (ori_ca <= 0) {
14022 flipshpush(&(flipshs[1]));
14025 *searchsh = flipshs[0];
14028 return sscoutsegment(searchsh, endpt, insertsegflag, reporterrorflag,
14040 void tetgenmesh::scarveholes(
int holes, REAL* holelist)
14042 face *parysh, searchsh, neighsh;
14043 enum locateresult loc;
14047 smarktest(recentsh);
14048 caveshlist->newindex((
void **) &parysh);
14049 *parysh = recentsh;
14050 for (i = 0; i < caveshlist->objects; i++) {
14051 parysh = (face *) fastlookup(caveshlist, i);
14052 searchsh = *parysh;
14053 searchsh.shver = 0;
14054 for (j = 0; j < 3; j++) {
14055 spivot(searchsh, neighsh);
14057 if (neighsh.sh != NULL) {
14058 if (!smarktested(neighsh)) {
14059 smarktest(neighsh);
14060 caveshlist->newindex((
void **) &parysh);
14065 if (!isshsubseg(searchsh)) {
14067 if (!sinfected(searchsh)) {
14069 caveshbdlist->newindex((
void **) &parysh);
14070 *parysh = searchsh;
14074 senextself(searchsh);
14079 for (i = 0; i < 3 * holes; i += 3) {
14080 searchsh = recentsh;
14081 loc = slocate(&(holelist[i]), &searchsh, 1, 1, 0);
14082 if (loc != OUTSIDE) {
14084 caveshbdlist->newindex((
void **) &parysh);
14085 *parysh = searchsh;
14090 for (i = 0; i < caveshbdlist->objects; i++) {
14091 parysh = (face *) fastlookup(caveshbdlist, i);
14092 searchsh = *parysh;
14093 searchsh.shver = 0;
14094 for (j = 0; j < 3; j++) {
14095 spivot(searchsh, neighsh);
14096 if (neighsh.sh != NULL) {
14097 if (!isshsubseg(searchsh)) {
14098 if (!sinfected(neighsh)) {
14100 caveshbdlist->newindex((
void **) &parysh);
14104 sdissolve(neighsh);
14107 senextself(searchsh);
14112 for (i = 0; i < caveshlist->objects; i++) {
14113 parysh = (face *) fastlookup(caveshlist, i);
14114 if (sinfected(*parysh)) {
14115 shellfacedealloc(subfaces, parysh->sh);
14117 sunmarktest(*parysh);
14121 caveshlist->restart();
14122 caveshbdlist->restart();
14137 int tetgenmesh::triangulate(
int shmark, arraypool* ptlist, arraypool* conlist,
14138 int holes, REAL* holelist)
14140 face searchsh, newsh, *parysh;
14141 face newseg, *paryseg;
14142 point pa, pb, pc, *ppt, *cons;
14146 if (b->verbose > 2) {
14147 printf(
" f%d: %ld vertices, %ld segments", shmark, ptlist->objects,
14150 printf(
", %d holes", holes);
14155 if (ptlist->objects < 2l) {
14158 }
else if (ptlist->objects == 2l) {
14159 pa = * (point *) fastlookup(ptlist, 0);
14160 pb = * (point *) fastlookup(ptlist, 1);
14161 if (distance(pa, pb) > 0) {
14163 makeshellface(subsegs, &newseg);
14164 setshvertices(newseg, pa, pb, NULL);
14165 setshellmark(newseg, -1);
14167 if (pointtype(pa) == VOLVERTEX) {
14168 setpointtype(pa, FACETVERTEX);
14170 if (pointtype(pb) == VOLVERTEX) {
14171 setpointtype(pb, FACETVERTEX);
14174 }
else if (ptlist->objects == 3) {
14175 pa = * (point *) fastlookup(ptlist, 0);
14176 pb = * (point *) fastlookup(ptlist, 1);
14177 pc = * (point *) fastlookup(ptlist, 2);
14180 if (!calculateabovepoint(ptlist, &pa, &pb, &pc)) {
14182 printf(
"Warning: Unable to triangulate facet #%d. Skipped!\n",shmark);
14189 makeshellface(subfaces, &newsh);
14190 setshvertices(newsh, pa, pb, pc);
14191 setshellmark(newsh, shmark);
14194 if (pointtype(pa) == VOLVERTEX) {
14195 setpointtype(pa, FACETVERTEX);
14197 if (pointtype(pb) == VOLVERTEX) {
14198 setpointtype(pb, FACETVERTEX);
14200 if (pointtype(pc) == VOLVERTEX) {
14201 setpointtype(pc, FACETVERTEX);
14205 if (b->quality && (in->facetconstraintlist != NULL)) {
14206 for (i = 0; i < in->numberoffacetconstraints; i++) {
14207 if (shmark == ((
int) in->facetconstraintlist[i * 2])) {
14208 REAL area = in->facetconstraintlist[i * 2 + 1];
14209 setareabound(newsh, area);
14215 if (ptlist->objects == 3) {
14217 for (i = 0; i < 3; i++) {
14218 makeshellface(subsegs, &newseg);
14219 setshvertices(newseg, sorg(newsh), sdest(newsh), NULL);
14220 setshellmark(newseg, -1);
14221 ssbond(newsh, newseg);
14231 caveencshlist->newindex((
void **) &parysh);
14238 for (i = 0; i < ptlist->objects; i++) {
14239 ppt = (point *) fastlookup(ptlist, i);
14240 if (!pinfected(*ppt)) {
14241 searchsh = recentsh;
14242 iloc = (int) OUTSIDE;
14244 iloc = sinsertvertex(*ppt, &searchsh, NULL, iloc, 1, 1);
14245 if (iloc != ((
int) ONVERTEX)) {
14247 if (pointtype(*ppt) == VOLVERTEX) {
14248 setpointtype(*ppt, FACETVERTEX);
14251 for (j = 0; j < caveshbdlist->objects; j++) {
14253 parysh = (face *) fastlookup(caveshbdlist, j);
14254 spivot(*parysh, searchsh);
14256 if (searchsh.sh[3] != NULL) {
14257 caveencshlist->newindex((
void **) &parysh);
14258 *parysh = searchsh;
14262 for (j = 0; j < caveshlist->objects; j++) {
14263 parysh = (face *) fastlookup(caveshlist, j);
14264 shellfacedealloc(subfaces, parysh->sh);
14267 caveshbdlist->restart();
14268 caveshlist->restart();
14269 cavesegshlist->restart();
14280 if (i < ptlist->objects) {
14284 printf(
"Warning: Fail to triangulate facet #%d. Skipped!\n", shmark);
14286 for (i = 0; i < caveencshlist->objects; i++) {
14287 parysh = (face *) fastlookup(caveencshlist, i);
14288 if (parysh->sh[3] != NULL) {
14289 shellfacedealloc(subfaces, parysh->sh);
14292 caveencshlist->restart();
14297 for (i = 0; i < conlist->objects; i++) {
14298 cons = (point *) fastlookup(conlist, i);
14299 searchsh = recentsh;
14300 iloc = (int) slocate(cons[0], &searchsh, 1, 1, 0);
14301 if (iloc != (
int) ONVERTEX) {
14303 subfaces->traversalinit();
14304 searchsh.sh = shellfacetraverse(subfaces);
14305 while (searchsh.sh != NULL) {
14307 if (shellmark(searchsh) == shmark) {
14308 if ((point) searchsh.sh[3] == cons[0]) {
14309 searchsh.shver = 0;
break;
14310 }
else if ((point) searchsh.sh[4] == cons[0]) {
14311 searchsh.shver = 2;
break;
14312 }
else if ((point) searchsh.sh[5] == cons[0]) {
14313 searchsh.shver = 4;
break;
14316 searchsh.sh = shellfacetraverse(subfaces);
14320 if (sscoutsegment(&searchsh, cons[1], 1, 1, 0) != SHAREEDGE) {
14324 sspivot(searchsh, newseg);
14325 caveencseglist->newindex((
void **) &paryseg);
14327 if (flipstack != NULL) {
14333 if (i < conlist->objects) {
14335 printf(
"Warning: Fail to recover a segment in facet #%d. Skipped!\n",
14338 for (i = 0; i < caveencshlist->objects; i++) {
14339 parysh = (face *) fastlookup(caveencshlist, i);
14340 if (parysh->sh[3] != NULL) {
14341 shellfacedealloc(subfaces, parysh->sh);
14344 for (i = 0; i < caveencseglist->objects; i++) {
14345 paryseg = (face *) fastlookup(caveencseglist, i);
14346 if (paryseg->sh[3] != NULL) {
14347 shellfacedealloc(subsegs, paryseg->sh);
14350 caveencshlist->restart();
14351 caveencseglist->restart();
14356 scarveholes(holes, holelist);
14358 caveencshlist->restart();
14359 caveencseglist->restart();
14372 void tetgenmesh::unifysegments()
14374 badface *facelink = NULL, *newlinkitem, *f1, *f2;
14375 face *facperverlist, sface;
14376 face subsegloop, testseg;
14378 REAL ori1, ori2, ori3;
14380 REAL cosang, ang, ang_tol;
14384 if (b->verbose > 1) {
14385 printf(
" Unifying segments.\n");
14388 ang_tol = b->facet_overlap_ang_tol / 180.0 * PI;
14389 if (ang_tol < 0.0) ang_tol = 0.0;
14392 makepoint2submap(subfaces, idx2faclist, facperverlist);
14395 subsegloop.shver = 0;
14396 subsegs->traversalinit();
14397 subsegloop.sh = shellfacetraverse(subsegs);
14398 while (subsegloop.sh != (shellface *) NULL) {
14399 torg = sorg(subsegloop);
14400 tdest = sdest(subsegloop);
14402 idx = pointmark(torg) - in->firstnumber;
14407 for (k = idx2faclist[idx]; k < idx2faclist[idx + 1]; k++) {
14408 sface = facperverlist[k];
14410 if (sface.sh[3] == NULL)
continue;
14412 if (sdest(sface) != tdest) {
14413 senext2self(sface);
14416 if (sdest(sface) != tdest)
continue;
14419 if (flippool->items >= 2) {
14421 for (m = 0; m < flippool->items - 1; m++) {
14423 ori1 = orient3d(torg, tdest, sapex(f1->ss), sapex(f2->ss));
14424 ori2 = orient3d(torg, tdest, sapex(f1->ss), sapex(sface));
14429 ori3 = orient3d(torg, tdest, sapex(f2->ss), sapex(sface));
14433 }
else if (ori3 < 0) {
14437 report_overlapping_facets(&(f2->ss), &sface);
14440 }
else if (ori2 < 0) {
14445 ori3 = orient3d(torg, tdest, sapex(f2->ss), sapex(sface));
14451 report_overlapping_facets(&(f1->ss), &sface);
14455 }
else if (ori1 < 0) {
14459 }
else if (ori2 < 0) {
14461 ori3 = orient3d(torg, tdest, sapex(f2->ss), sapex(sface));
14465 }
else if (ori3 < 0) {
14469 report_overlapping_facets(&(f2->ss), &sface);
14474 ori3 = orient3d(torg, tdest, sapex(f2->ss), sapex(sface));
14477 report_overlapping_facets(&(f1->ss), &sface);
14488 }
else if (ori2 < 0) {
14494 facenormal(torg, tdest, sapex(f1->ss), n1, 1, NULL);
14495 facenormal(torg, tdest, sapex(sface), n2, 1, NULL);
14496 if (dot(n1, n2) > 0) {
14497 report_overlapping_facets(&(f1->ss), &sface);
14499 report_overlapping_facets(&(f2->ss), &sface);
14507 if (sface.sh[3] != NULL) {
14509 newlinkitem = (badface *) flippool->alloc();
14510 newlinkitem->ss = sface;
14511 newlinkitem->nextitem = f1->nextitem;
14512 f1->nextitem = newlinkitem;
14514 }
else if (flippool->items == 1) {
14517 ori1 = orient3d(torg, tdest, sapex(f1->ss), sapex(sface));
14520 facenormal(torg, tdest, sapex(f1->ss), n1, 1, NULL);
14521 facenormal(torg, tdest, sapex(sface), n2, 1, NULL);
14522 if (dot(n1, n2) > 0) {
14524 report_overlapping_facets(&(f1->ss), &sface);
14528 if (sface.sh[3] != NULL) {
14530 newlinkitem = (badface *) flippool->alloc();
14531 newlinkitem->ss = sface;
14532 newlinkitem->nextitem = NULL;
14533 f1->nextitem = newlinkitem;
14537 newlinkitem = (badface *) flippool->alloc();
14538 newlinkitem->ss = sface;
14539 newlinkitem->nextitem = NULL;
14540 facelink = newlinkitem;
14548 for (k = 0; k < flippool->items; k++) {
14549 sspivot(f1->ss, testseg);
14551 if ((testseg.sh != subsegloop.sh) && (testseg.sh[3] != NULL)) {
14552 shellfacedealloc(subsegs, testseg.sh);
14555 ssbond(f1->ss, subsegloop);
14560 if (flippool->items > 1) {
14562 for (k = 1; k <= flippool->items; k++) {
14563 k < flippool->items ? f2 = f1->nextitem : f2 = facelink;
14565 facenormal(torg, tdest, sapex(f1->ss), n1, 1, NULL);
14566 facenormal(torg, tdest, sapex(f2->ss), n2, 1, NULL);
14567 cosang = dot(n1, n2) / (sqrt(dot(n1, n1)) * sqrt(dot(n2, n2)));
14569 if (cosang > 1.0) cosang = 1.0;
14570 else if (cosang < -1.0) cosang = -1.0;
14571 ang = acos(cosang);
14572 if (ang < ang_tol) {
14574 report_overlapping_facets(&(f1->ss), &(f2->ss), ang);
14577 if (ang < minfacetdihed) {
14578 minfacetdihed = ang;
14580 sbond1(f1->ss, f2->ss);
14586 flippool->restart();
14589 if (b->quality && (in->segmentconstraintlist != (REAL *) NULL)) {
14592 for (k = 0; k < in->numberofsegmentconstraints; k++) {
14593 e1 = (int) in->segmentconstraintlist[k * 3];
14594 e2 = (
int) in->segmentconstraintlist[k * 3 + 1];
14595 if (((pointmark(torg) == e1) && (pointmark(tdest) == e2)) ||
14596 ((pointmark(torg) == e2) && (pointmark(tdest) == e1))) {
14597 len = in->segmentconstraintlist[k * 3 + 2];
14598 setareabound(subsegloop, len);
14604 subsegloop.sh = shellfacetraverse(subsegs);
14607 delete [] idx2faclist;
14608 delete [] facperverlist;
14623 void tetgenmesh::identifyinputedges(point *idx2verlist)
14625 face* shperverlist;
14627 face searchsh, neighsh;
14628 face segloop, checkseg, newseg;
14629 point checkpt, pa = NULL, pb = NULL;
14638 printf(
"Inserting edges ...\n");
14642 makepoint2submap(subfaces, idx2shlist, shperverlist);
14645 for (i = 0; i < in->numberofedges; i++) {
14646 endpts = &(in->edgelist[(i << 1)]);
14647 if (endpts[0] == endpts[1]) {
14649 printf(
"Warning: Edge #%d is degenerated. Skipped.\n", i);
14655 edgemarker = in->edgemarkerlist ? in->edgemarkerlist[i] : -2;
14659 searchsh.sh = NULL;
14660 idx = endpts[0] - in->firstnumber;
14661 for (j = idx2shlist[idx]; j < idx2shlist[idx + 1]; j++) {
14662 checkpt = sdest(shperverlist[j]);
14663 if (pointmark(checkpt) == endpts[1]) {
14664 searchsh = shperverlist[j];
14667 checkpt = sapex(shperverlist[j]);
14668 if (pointmark(checkpt) == endpts[1]) {
14669 senext2(shperverlist[j], searchsh);
14670 sesymself(searchsh);
14676 if (searchsh.sh != NULL) {
14678 sspivot(searchsh, checkseg);
14679 if (checkseg.sh != NULL) {
14684 pa = sorg(searchsh);
14685 pb = sdest(searchsh);
14686 makeshellface(subsegs, &newseg);
14687 setshvertices(newseg, pa, pb, NULL);
14688 ssbond(searchsh, newseg);
14689 spivot(searchsh, neighsh);
14690 if (neighsh.sh != NULL) {
14691 ssbond(neighsh, newseg);
14697 pa = idx2verlist[endpts[0]];
14698 pb = idx2verlist[endpts[1]];
14701 printf(
"Warning: Edge #%d is degenerated. Skipped.\n", i);
14708 subsegs->traversalinit();
14709 segloop.sh = shellfacetraverse(subsegs);
14710 while (segloop.sh != NULL) {
14711 ppt = (point *) &(segloop.sh[3]);
14712 if (((ppt[0] == pa) && (ppt[1] == pb)) ||
14713 ((ppt[0] == pb) && (ppt[1] == pa))) {
14718 segloop.sh = shellfacetraverse(subsegs);
14720 if (newseg.sh == NULL) {
14721 makeshellface(subsegs, &newseg);
14722 setshvertices(newseg, pa, pb, NULL);
14726 setshellmark(newseg, edgemarker);
14728 if (b->quality && (in->segmentconstraintlist != (REAL *) NULL)) {
14729 for (i = 0; i < in->numberofsegmentconstraints; i++) {
14730 e1 = (int) in->segmentconstraintlist[i * 3];
14731 e2 = (
int) in->segmentconstraintlist[i * 3 + 1];
14732 if (((pointmark(pa) == e1) && (pointmark(pb) == e2)) ||
14733 ((pointmark(pa) == e2) && (pointmark(pb) == e1))) {
14734 len = in->segmentconstraintlist[i * 3 + 2];
14735 setareabound(newseg, len);
14742 delete [] shperverlist;
14743 delete [] idx2shlist;
14752 void tetgenmesh::mergefacets()
14754 face parentsh, neighsh, neineish;
14756 point pa, pb, pc, pd;
14758 REAL cosang, cosang_tol;
14762 arraypool *dihedangarray =
new arraypool(
sizeof(
double), 10);
14763 REAL *paryang = NULL;
14767 cosang_tol = cos(b->facet_separate_ang_tol / 180.0 * PI);
14769 subsegs->traversalinit();
14770 segloop.sh = shellfacetraverse(subsegs);
14771 while (segloop.sh != (shellface *) NULL) {
14773 if (shellmark(segloop) != -1) {
14774 segloop.sh = shellfacetraverse(subsegs);
14777 spivot(segloop, parentsh);
14778 if (parentsh.sh != NULL) {
14779 spivot(parentsh, neighsh);
14780 if (neighsh.sh != NULL) {
14781 spivot(neighsh, neineish);
14782 if (neineish.sh == parentsh.sh) {
14785 if (shellmark(parentsh) == shellmark(neighsh)) {
14786 pa = sorg(segloop);
14787 pb = sdest(segloop);
14788 pc = sapex(parentsh);
14789 pd = sapex(neighsh);
14791 facenormal(pa, pb, pc, n1, 1, NULL);
14792 facenormal(pa, pb, pd, n2, 1, NULL);
14793 cosang = dot(n1, n2) / (sqrt(dot(n1, n1)) * sqrt(dot(n2, n2)));
14794 if (cosang < cosang_tol) {
14795 ssdissolve(parentsh);
14796 ssdissolve(neighsh);
14797 shellfacedealloc(subsegs, segloop.sh);
14799 flipshpush(&parentsh);
14803 dihedangarray->newindex((
void **) &paryang);
14805 segloop.sh[6] = (shellface) paryang;
14811 segloop.sh = shellfacetraverse(subsegs);
14816 cosang_tol = cos(b->facet_small_ang_tol / 180.0 * PI);
14817 REAL cosang_sep_tol = cos((b->facet_separate_ang_tol - 5.0) / 180.0 * PI);
14820 REAL cosang1, cosang2;
14823 subfaces->traversalinit();
14824 shloop.sh = shellfacetraverse(subfaces);
14825 while (shloop.sh != (shellface *) NULL) {
14826 for (i = 0; i < 3; i++) {
14827 if (isshsubseg(shloop)) {
14828 senext(shloop, neighsh);
14829 if (isshsubseg(neighsh)) {
14833 pb = sdest(shloop);
14834 pc = sapex(shloop);
14835 for (j = 0; j < 3; j++) n1[j] = pa[j] - pb[j];
14836 for (j = 0; j < 3; j++) n2[j] = pc[j] - pb[j];
14837 cosang = dot(n1, n2) / (sqrt(dot(n1, n1)) * sqrt(dot(n2, n2)));
14838 if (cosang > cosang_tol) {
14841 sspivot(shloop, seg1);
14842 sspivot(neighsh, seg2);
14843 if (seg1.sh[6] != NULL) {
14844 paryang = (REAL *) (seg1.sh[6]);
14845 cosang1 = *paryang;
14849 if (seg2.sh[6] != NULL) {
14850 paryang = (REAL *) (seg2.sh[6]);
14851 cosang2 = *paryang;
14855 if (cosang1 < cosang_sep_tol) {
14856 if (cosang2 < cosang_sep_tol) {
14857 if (cosang1 < cosang2) {
14866 if (cosang2 < cosang_sep_tol) {
14870 if (segloop.sh != NULL) {
14873 spivot(segloop, parentsh);
14874 spivot(parentsh, neighsh);
14875 ssdissolve(parentsh);
14876 ssdissolve(neighsh);
14877 shellfacedealloc(subsegs, segloop.sh);
14879 flipshpush(&parentsh);
14885 senextself(shloop);
14887 shloop.sh = shellfacetraverse(subfaces);
14890 delete dihedangarray;
14892 if (flipstack != NULL) {
14903 void tetgenmesh::meshsurface()
14905 arraypool *ptlist, *conlist;
14906 point *idx2verlist;
14907 point tstart, tend, *pnewpt, *cons;
14914 printf(
"Creating surface mesh ...\n");
14918 makeindex2pointmap(idx2verlist);
14921 ptlist =
new arraypool(
sizeof(point *), 8);
14922 conlist =
new arraypool(2 *
sizeof(point *), 8);
14925 for (shmark = 1; shmark <= in->numberoffacets; shmark++) {
14928 f = &in->facetlist[shmark - 1];
14933 if (dupverts > 0l) {
14935 for (i = 0; i < f->numberofpolygons; i++) {
14936 p = &(f->polygonlist[i]);
14938 for (j = 0; j < p->numberofvertices; j++) {
14939 end1 = p->vertexlist[j];
14940 tstart = idx2verlist[end1];
14941 if (pointtype(tstart) == DUPLICATEDVERTEX) {
14943 tend = point2ppt(tstart);
14944 end2 = pointmark(tend);
14945 p->vertexlist[j] = end2;
14952 for (i = 0; i < f->numberofpolygons; i++) {
14954 p = &(f->polygonlist[i]);
14956 end1 = p->vertexlist[0];
14957 if ((end1 < in->firstnumber) ||
14958 (end1 >= in->firstnumber + in->numberofpoints)) {
14960 printf(
"Warning: Invalid the 1st vertex %d of polygon", end1);
14961 printf(
" %d in facet %d.\n", i + 1, shmark);
14965 tstart = idx2verlist[end1];
14967 if (!pinfected(tstart)) {
14969 ptlist->newindex((
void **) &pnewpt);
14973 for (j = 1; j <= p->numberofvertices; j++) {
14975 if (j < p->numberofvertices) {
14976 end2 = p->vertexlist[j];
14978 end2 = p->vertexlist[0];
14980 if ((end2 < in->firstnumber) ||
14981 (end2 >= in->firstnumber + in->numberofpoints)) {
14983 printf(
"Warning: Invalid vertex %d in polygon %d", end2, i + 1);
14984 printf(
" in facet %d.\n", shmark);
14987 if (end1 != end2) {
14989 tend = idx2verlist[end2];
14991 if (!pinfected(tend)) {
14993 ptlist->newindex((
void **) &pnewpt);
14997 conlist->newindex((
void **) &cons);
15005 if (p->numberofvertices > 2) {
15009 printf(
"Warning: Polygon %d has two identical verts", i + 1);
15010 printf(
" in facet %d.\n", shmark);
15017 if (p->numberofvertices == 2)
break;
15021 for (i = 0; i < ptlist->objects; i++) {
15022 pnewpt = (point *) fastlookup(ptlist, i);
15023 puninfect(*pnewpt);
15028 triangulate(in->facetmarkerlist ? in->facetmarkerlist[shmark - 1] : -1,
15029 ptlist, conlist, f->numberofholes, f->holelist);
15033 conlist->restart();
15036 if (!b->diagnose) {
15039 if (in->numberofedges > 0) {
15041 identifyinputedges(idx2verlist);
15043 if (!b->psc && !b->nomergefacet &&
15044 (!b->nobisect || (b->nobisect && !b->nobisect_nomerge))) {
15050 if (b->object == tetgenbehavior::STL) {
15056 printf(
" %ld (%ld) subfaces (segments).\n", subfaces->items,
15061 insegments = subsegs->items;
15063 delete [] idx2verlist;
15092 void tetgenmesh::interecursive(shellface** subfacearray,
int arraysize,
15093 int axis, REAL bxmin, REAL bxmax, REAL bymin,
15094 REAL bymax, REAL bzmin, REAL bzmax,
15097 shellface **leftarray, **rightarray;
15098 face sface1, sface2;
15101 enum interresult intersect;
15103 bool toleft, toright;
15104 int leftsize, rightsize;
15107 if (b->verbose > 2) {
15108 printf(
" Recur %d faces. Bbox (%g, %g, %g),(%g, %g, %g). %s-axis\n",
15109 arraysize, bxmin, bymin, bzmin, bxmax, bymax, bzmax,
15110 axis == 0 ?
"x" : (axis == 1 ?
"y" :
"z"));
15113 leftarray =
new shellface*[arraysize];
15114 if (leftarray == NULL) {
15115 terminatetetgen(
this, 1);
15117 rightarray =
new shellface*[arraysize];
15118 if (rightarray == NULL) {
15119 terminatetetgen(
this, 1);
15121 leftsize = rightsize = 0;
15125 split = 0.5 * (bxmin + bxmax);
15126 }
else if (axis == 1) {
15128 split = 0.5 * (bymin + bymax);
15131 split = 0.5 * (bzmin + bzmax);
15134 for (i = 0; i < arraysize; i++) {
15135 sface1.sh = subfacearray[i];
15136 p1 = (point) sface1.sh[3];
15137 p2 = (point) sface1.sh[4];
15138 p3 = (point) sface1.sh[5];
15139 toleft = toright =
false;
15140 if (p1[axis] < split) {
15142 if (p2[axis] >= split || p3[axis] >= split) {
15145 }
else if (p1[axis] > split) {
15147 if (p2[axis] <= split || p3[axis] <= split) {
15156 leftarray[leftsize] = sface1.sh;
15160 rightarray[rightsize] = sface1.sh;
15165 if (leftsize < arraysize && rightsize < arraysize) {
15170 delete [] subfacearray;
15173 interecursive(leftarray, leftsize, 1, bxmin, split, bymin, bymax,
15174 bzmin, bzmax, internum);
15175 interecursive(rightarray, rightsize, 1, split, bxmax, bymin, bymax,
15176 bzmin, bzmax, internum);
15177 }
else if (axis == 1) {
15178 interecursive(leftarray, leftsize, 2, bxmin, bxmax, bymin, split,
15179 bzmin, bzmax, internum);
15180 interecursive(rightarray, rightsize, 2, bxmin, bxmax, split, bymax,
15181 bzmin, bzmax, internum);
15183 interecursive(leftarray, leftsize, 0, bxmin, bxmax, bymin, bymax,
15184 bzmin, split, internum);
15185 interecursive(rightarray, rightsize, 0, bxmin, bxmax, bymin, bymax,
15186 split, bzmax, internum);
15189 if (b->verbose > 1) {
15190 printf(
" Checking intersecting faces.\n");
15193 for (i = 0; i < arraysize; i++) {
15194 sface1.sh = subfacearray[i];
15195 p1 = (point) sface1.sh[3];
15196 p2 = (point) sface1.sh[4];
15197 p3 = (point) sface1.sh[5];
15198 for (j = i + 1; j < arraysize; j++) {
15199 sface2.sh = subfacearray[j];
15200 p4 = (point) sface2.sh[3];
15201 p5 = (point) sface2.sh[4];
15202 p6 = (point) sface2.sh[5];
15203 intersect = (
enum interresult) tri_tri_inter(p1, p2, p3, p4, p5, p6);
15204 if (intersect == INTERSECT || intersect == SHAREFACE) {
15206 if (intersect == INTERSECT) {
15207 printf(
" Facet #%d intersects facet #%d at triangles:\n",
15208 shellmark(sface1), shellmark(sface2));
15209 printf(
" (%4d, %4d, %4d) and (%4d, %4d, %4d)\n",
15210 pointmark(p1), pointmark(p2), pointmark(p3),
15211 pointmark(p4), pointmark(p5), pointmark(p6));
15213 printf(
" Facet #%d duplicates facet #%d at triangle:\n",
15214 shellmark(sface1), shellmark(sface2));
15215 printf(
" (%4d, %4d, %4d) and (%4d, %4d, %4d)\n",
15216 pointmark(p1), pointmark(p2), pointmark(p3),
15217 pointmark(p4), pointmark(p5), pointmark(p6));
15229 delete [] leftarray;
15230 delete [] rightarray;
15231 delete [] subfacearray;
15260 void tetgenmesh::detectinterfaces()
15262 shellface **subfacearray;
15268 printf(
"Detecting self-intersecting facets...\n");
15272 subfacearray =
new shellface*[subfaces->items];
15273 subfaces->traversalinit();
15274 shloop.sh = shellfacetraverse(subfaces);
15276 while (shloop.sh != (shellface *) NULL) {
15277 subfacearray[i] = shloop.sh;
15278 shloop.sh = shellfacetraverse(subfaces);
15286 interecursive(subfacearray, subfaces->items, 0, xmin, xmax, ymin, ymax,
15287 zmin, zmax, &internum);
15290 if (internum > 0) {
15291 printf(
"\n!! Found %d pairs of faces are intersecting.\n\n", internum);
15293 printf(
"\nNo faces are intersecting.\n\n");
15297 if (internum > 0) {
15301 subfaces->traversalinit();
15302 shloop.sh = shellfacetraverse(subfaces);
15303 while (shloop.sh != (shellface *) NULL) {
15304 if (sinfected(shloop)) {
15307 shellfacedealloc(subfaces, shloop.sh);
15309 shloop.sh = shellfacetraverse(subfaces);
15313 subfaces->restart();
15335 void tetgenmesh::makesegmentendpointsmap()
15337 arraypool *segptlist;
15338 face segloop, prevseg, nextseg;
15339 point eorg, edest, *parypt;
15340 int segindex = 0, idx = 0;
15343 if (b->verbose > 0) {
15344 printf(
" Creating the segment-endpoints map.\n");
15347 segptlist =
new arraypool(2 *
sizeof(point), 10);
15351 subsegs->traversalinit();
15352 segloop.sh = shellfacetraverse(subsegs);
15354 while (segloop.sh != NULL) {
15355 senext2(segloop, prevseg);
15356 spivotself(prevseg);
15357 if (prevseg.sh == NULL) {
15358 eorg = sorg(segloop);
15359 edest = sdest(segloop);
15360 setfacetindex(segloop, segindex);
15361 senext(segloop, nextseg);
15362 spivotself(nextseg);
15363 while (nextseg.sh != NULL) {
15364 setfacetindex(nextseg, segindex);
15366 if (sorg(nextseg) != edest) sesymself(nextseg);
15367 edest = sdest(nextseg);
15369 senextself(nextseg);
15370 spivotself(nextseg);
15372 segptlist->newindex((
void **) &parypt);
15377 segloop.sh = shellfacetraverse(subsegs);
15381 printf(
" Found %ld segments.\n", segptlist->objects);
15384 segmentendpointslist =
new point[segptlist->objects * 2];
15386 totalworkmemory += (segptlist->objects * 2) *
sizeof(point *);
15388 for (i = 0; i < segptlist->objects; i++) {
15389 parypt = (point *) fastlookup(segptlist, i);
15390 segmentendpointslist[idx++] = parypt[0];
15391 segmentendpointslist[idx++] = parypt[1];
15415 enum tetgenmesh::interresult
15416 tetgenmesh::finddirection(triface* searchtet, point endpt)
15419 point pa, pb, pc, pd;
15420 enum {HMOVE, RMOVE, LMOVE} nextmove;
15421 REAL hori, rori, lori;
15426 pa = org(*searchtet);
15427 if ((point) searchtet->tet[7] == dummypoint) {
15429 decode(searchtet->tet[3], *searchtet);
15431 if ((point) searchtet->tet[4] == pa) {
15432 searchtet->ver = 11;
15433 }
else if ((point) searchtet->tet[5] == pa) {
15434 searchtet->ver = 3;
15435 }
else if ((point) searchtet->tet[6] == pa) {
15436 searchtet->ver = 7;
15438 searchtet->ver = 0;
15442 pb = dest(*searchtet);
15449 pc = apex(*searchtet);
15452 eprevesymself(*searchtet);
15459 pd = oppo(*searchtet);
15463 esymself(*searchtet);
15464 enextself(*searchtet);
15468 if (pd == dummypoint) {
15473 terminatetetgen(
this, 2);
15482 hori = orient3d(pa, pb, pc, endpt);
15483 rori = orient3d(pb, pa, pd, endpt);
15484 lori = orient3d(pa, pc, pd, endpt);
15492 s = randomnation(3);
15495 }
else if (s == 1) {
15502 if (randomnation(2)) {
15511 if (randomnation(2)) {
15525 if (randomnation(2)) {
15547 eprevesymself(*searchtet);
15556 esymself(*searchtet);
15557 enextself(*searchtet);
15561 esymself(*searchtet);
15562 enextself(*searchtet);
15567 eprevesymself(*searchtet);
15577 if (nextmove == RMOVE) {
15578 fnextself(*searchtet);
15579 }
else if (nextmove == LMOVE) {
15580 eprevself(*searchtet);
15581 fnextself(*searchtet);
15582 enextself(*searchtet);
15584 fsymself(*searchtet);
15585 enextself(*searchtet);
15587 pb = dest(*searchtet);
15588 pc = apex(*searchtet);
15612 enum tetgenmesh::interresult tetgenmesh::scoutsegment(point startpt,point endpt,
15613 face *sedge, triface* searchtet, point* refpt, arraypool* intfacelist)
15616 enum interresult dir;
15619 if (b->verbose > 2) {
15620 printf(
" Scout seg (%d, %d).\n",pointmark(startpt),pointmark(endpt));
15623 point2tetorg(startpt, *searchtet);
15624 dir = finddirection(searchtet, endpt);
15626 if (dir == ACROSSVERT) {
15627 pd = dest(*searchtet);
15629 if (issubseg(*searchtet)) {
15630 report_selfint_edge(startpt, endpt, sedge, searchtet, dir);
15635 report_selfint_edge(startpt, endpt, sedge, searchtet, dir);
15641 enextesymself(*searchtet);
15642 fsymself(*searchtet);
15644 if (dir == ACROSSEDGE) {
15646 if (issubseg(*searchtet)) {
15647 report_selfint_edge(startpt, endpt, sedge, searchtet, dir);
15649 }
else if (dir == ACROSSFACE) {
15650 if (checksubfaceflag) {
15652 if (issubface(*searchtet)) {
15653 report_selfint_edge(startpt, endpt, sedge, searchtet, dir);
15657 terminatetetgen(
this, 2);
15660 if (refpt == NULL) {
15665 triface neightet, reftet;
15668 int types[2], poss[4];
15671 pa = org(*searchtet);
15672 angmax = interiorangle(pa, startpt, endpt, NULL);
15674 pb = dest(*searchtet);
15675 ang = interiorangle(pb, startpt, endpt, NULL);
15676 if (ang > angmax) {
15680 pc = apex(*searchtet);
15681 ang = interiorangle(pc, startpt, endpt, NULL);
15682 if (ang > angmax) {
15686 reftet = *searchtet;
15692 pd = oppo(*searchtet);
15696 if (pd == endpt)
break;
15698 ang = interiorangle(pd, startpt, endpt, NULL);
15699 if (ang > angmax) {
15702 reftet = *searchtet;
15706 if (dir == ACROSSFACE) {
15708 neightet = *searchtet;
15709 j = (neightet.ver & 3);
15710 for (i = j + 1; i < j + 4; i++) {
15711 neightet.ver = (i % 4);
15712 pa = org(neightet);
15713 pb = dest(neightet);
15714 pc = apex(neightet);
15715 pd = oppo(neightet);
15716 if (tri_edge_test(pa, pb, pc, startpt, endpt, pd, 1, types, poss)) {
15717 dir = (
enum interresult) types[0];
15725 }
else if (dir == ACROSSEDGE) {
15727 for (i = 0; i < 2; i++) {
15729 enextesym(*searchtet, neightet);
15731 eprevesym(*searchtet, neightet);
15733 pa = org(neightet);
15734 pb = dest(neightet);
15735 pc = apex(neightet);
15736 pd = oppo(neightet);
15737 if (tri_edge_test(pa, pb, pc, startpt, endpt, pd, 1, types, poss)) {
15738 dir = (
enum interresult) types[0];
15746 if (dir == DISJOINT) {
15749 fnextself(*searchtet);
15754 if (dir == ACROSSVERT) {
15756 for (i = 0; i < pos; i++) {
15757 enextself(neightet);
15759 eprev(neightet, *searchtet);
15761 report_selfint_edge(startpt, endpt, sedge, searchtet, dir);
15763 }
else if (dir == ACROSSEDGE) {
15765 for (i = 0; i < pos; i++) {
15766 enextself(neightet);
15770 fsym(neightet, *searchtet);
15772 if (dir == ACROSSEDGE) {
15774 if (issubseg(*searchtet)) {
15775 report_selfint_edge(startpt, endpt, sedge, searchtet, dir);
15777 }
else if (dir == ACROSSFACE) {
15778 if (checksubfaceflag) {
15780 if (issubface(*searchtet)) {
15781 report_selfint_edge(startpt, endpt, sedge, searchtet, dir);
15785 terminatetetgen(
this, 2);
15792 if (2.0 * angmax < PI) {
15797 *searchtet = reftet;
15810 int tetgenmesh::getsteinerptonsegment(face* seg, point refpt, point steinpt)
15812 point ei = sorg(*seg);
15813 point ej = sdest(*seg);
15814 int adjflag = 0, i;
15816 if (refpt != NULL) {
15819 if (pointtype(refpt) == FREESEGVERTEX) {
15821 sdecode(point2sh(refpt), parentseg);
15822 int sidx1 = getfacetindex(parentseg);
15823 point far_pi = segmentendpointslist[sidx1 * 2];
15824 point far_pj = segmentendpointslist[sidx1 * 2 + 1];
15825 int sidx2 = getfacetindex(*seg);
15826 point far_ei = segmentendpointslist[sidx2 * 2];
15827 point far_ej = segmentendpointslist[sidx2 * 2 + 1];
15828 if ((far_pi == far_ei) || (far_pj == far_ei)) {
15832 L = distance(far_ei, far_ej);
15833 L1 = distance(far_ei, refpt);
15835 for (i = 0; i < 3; i++) {
15836 steinpt[i] = far_ei[i] + t * (far_ej[i] - far_ei[i]);
15839 }
else if ((far_pi == far_ej) || (far_pj == far_ej)) {
15840 L = distance(far_ei, far_ej);
15841 L1 = distance(far_ej, refpt);
15843 for (i = 0; i < 3; i++) {
15844 steinpt[i] = far_ej[i] + t * (far_ei[i] - far_ej[i]);
15849 projpt2edge(refpt, ei, ej, steinpt);
15853 projpt2edge(refpt, ei, ej, steinpt);
15857 L = distance(ei, ej);
15858 L1 = distance(steinpt, ei);
15860 if ((t < 0.2) || (t > 0.8)) {
15862 for (i = 0; i < 3; i++) {
15863 steinpt[i] = ei[i] + 0.5 * (ej[i] - ei[i]);
15868 for (i = 0; i < 3; i++) {
15869 steinpt[i] = ei[i] + 0.5 * (ej[i] - ei[i]);
15893 void tetgenmesh::delaunizesegments()
15895 triface searchtet, spintet;
15898 point refpt, newpt;
15899 enum interresult dir;
15900 insertvertexflags ivf;
15905 ivf.sloc = (int) ONEDGE;
15907 ivf.assignmeshsize = b->metric;
15908 ivf.smlenflag = useinsertradius;
15911 while (subsegstack->objects > 0l) {
15913 subsegstack->objects--;
15914 psseg = (face *) fastlookup(subsegstack, subsegstack->objects);
15918 sstpivot1(sseg, searchtet);
15919 if (searchtet.tet != NULL) {
15924 dir = scoutsegment(sorg(sseg), sdest(sseg), &sseg,&searchtet,&refpt,NULL);
15926 if (dir == SHAREEDGE) {
15929 sstbond1(sseg, searchtet);
15931 spintet = searchtet;
15933 tssbond1(spintet, sseg);
15934 fnextself(spintet);
15935 }
while (spintet.tet != searchtet.tet);
15937 if ((dir == ACROSSFACE) || (dir == ACROSSEDGE)) {
15940 makepoint(&newpt, FREESEGVERTEX);
15942 getsteinerptonsegment(&sseg, refpt, newpt);
15945 ivf.iloc = (int) OUTSIDE;
15949 if (insertpoint(newpt, &searchtet, &searchsh, &sseg, &ivf)) {
15952 if (steinerleft > 0) steinerleft--;
15953 if (useinsertradius) {
15954 save_segmentpoint_insradius(newpt, ivf.parentpt, ivf.smlen);
15957 if (ivf.iloc == (
int) NEARVERTEX) {
15960 point nearpt = org(searchtet);
15961 if (pointtype(nearpt) == FREESEGVERTEX) {
15963 sdecode(point2sh(nearpt), parentseg);
15964 point p1 = farsorg(sseg);
15965 point p2 = farsdest(sseg);
15966 point p3 = farsorg(parentseg);
15967 point p4 = farsdest(parentseg);
15968 printf(
"Two segments are very close to each other.\n");
15969 printf(
" Segment 1: [%d, %d] #%d\n", pointmark(p1),
15970 pointmark(p2), shellmark(sseg));
15971 printf(
" Segment 2: [%d, %d] #%d\n", pointmark(p3),
15972 pointmark(p4), shellmark(parentseg));
15973 terminatetetgen(
this, 4);
15975 terminatetetgen(
this, 2);
15977 }
else if (ivf.iloc == (
int) ONVERTEX) {
15980 eprevself(searchtet);
15981 report_selfint_edge(sorg(sseg), sdest(sseg), &sseg, &searchtet,
15985 terminatetetgen(
this, 2);
15990 terminatetetgen(
this, 2);
16009 int tetgenmesh::scoutsubface(face* searchsh, triface* searchtet,
int shflag)
16011 point pa = sorg(*searchsh);
16012 point pb = sdest(*searchsh);
16015 point2tetorg(pa, *searchtet);
16017 enum interresult dir = finddirection(searchtet, pb);
16018 if (dir == ACROSSVERT) {
16020 if (dest(*searchtet) != pb) {
16023 report_selfint_edge(pa, pb, searchsh, searchtet, dir);
16025 terminatetetgen(
this, 2);
16030 point pc = sapex(*searchsh);
16032 triface spintet = *searchtet;
16034 if (apex(spintet) == pc) {
16036 if (!issubface(spintet)) {
16038 tsbond(spintet, *searchsh);
16040 sesymself(*searchsh);
16041 tsbond(spintet, *searchsh);
16042 *searchtet = spintet;
16045 terminatetetgen(
this, 2);
16048 fnextself(spintet);
16049 if (spintet.tet == searchtet->tet)
break;
16075 void tetgenmesh::formregion(face* missh, arraypool* missingshs,
16076 arraypool* missingshbds, arraypool* missingshverts)
16078 triface searchtet, spintet;
16079 face neighsh, *parysh;
16080 face neighseg, fakeseg;
16081 point pa, pb, *parypt;
16082 enum interresult dir;
16087 missingshs->newindex((
void **) &parysh);
16091 for (i = 0; i < missingshs->objects; i++) {
16092 missh = (face *) fastlookup(missingshs, i);
16093 for (j = 0; j < 3; j++) {
16095 pb = sdest(*missh);
16096 point2tetorg(pa, searchtet);
16097 dir = finddirection(&searchtet, pb);
16098 if (dir != ACROSSVERT) {
16100 spivot(*missh, neighsh);
16101 if (!smarktested(neighsh)) {
16103 if (sorg(neighsh) != pb) sesymself(neighsh);
16104 smarktest(neighsh);
16105 missingshs->newindex((
void **) &parysh);
16109 if (dest(searchtet) != pb) {
16111 report_selfint_edge(pa, pb, missh, &searchtet, dir);
16115 if (!pmarktested(pa)) {
16117 missingshverts->newindex((
void **) &parypt);
16120 senextself(*missh);
16125 for (i = 0; i < missingshs->objects; i++) {
16126 missh = (face *) fastlookup(missingshs, i);
16127 for (j = 0; j < 3; j++) {
16128 spivot(*missh, neighsh);
16129 if ((neighsh.sh == NULL) || !smarktested(neighsh)) {
16132 point2tetorg(sorg(*missh), searchtet);
16133 finddirection(&searchtet, sdest(*missh));
16134 missingshbds->newindex((
void **) &parysh);
16137 sspivot(*missh, neighseg);
16138 if (neighseg.sh == NULL) {
16140 makeshellface(subsegs, &fakeseg);
16141 setsorg(fakeseg, sorg(*missh));
16142 setsdest(fakeseg, sdest(*missh));
16145 spintet = searchtet;
16147 tssbond1(spintet, fakeseg);
16148 fnextself(spintet);
16149 if (spintet.tet == searchtet.tet)
break;
16151 neighseg = fakeseg;
16154 ssbond(*missh, neighseg);
16155 sstbond1(neighseg, searchtet);
16157 senextself(*missh);
16163 for (i = 0; i < missingshs->objects; i++) {
16164 parysh = (face *) fastlookup(missingshs, i);
16165 sunmarktest(*parysh);
16181 int tetgenmesh::scoutcrossedge(triface& crosstet, arraypool* missingshbds,
16182 arraypool* missingshs)
16184 triface searchtet, spintet, neightet;
16185 face oldsh, searchsh, *parysh;
16187 point pa, pb, pc, pd, pe;
16189 int types[2], poss[4];
16190 int searchflag, interflag;
16197 for (i = 0; i < missingshbds->objects && !searchflag; i++) {
16198 parysh = (face *) fastlookup(missingshbds, i);
16199 sspivot(*parysh, neighseg);
16200 sstpivot1(neighseg, searchtet);
16201 if (org(searchtet) != sorg(*parysh)) {
16202 esymself(searchtet);
16204 spintet = searchtet;
16206 if (pmarktested(apex(spintet))) {
16208 neightet = spintet;
16211 for (j = 0; j < 2; j++) {
16212 enextself(neightet);
16213 if (!issubseg(neightet)) {
16215 senext(oldsh, searchsh);
16217 senext2(oldsh, searchsh);
16218 sesymself(searchsh);
16219 esymself(neightet);
16222 pa = sorg(searchsh);
16223 pb = sdest(searchsh);
16224 pc = sapex(searchsh);
16225 pd = dest(neightet);
16226 calculateabovepoint4(pa, pb, pc, pd);
16228 ori = orient3d(pa, pb, pc, dummypoint);
16230 sesymself(searchsh);
16231 senextself(searchsh);
16232 }
else if (ori == 0) {
16233 terminatetetgen(
this, 2);
16235 if (sscoutsegment(&searchsh,dest(neightet),0,0,1)==SHAREEDGE) {
16238 makeshellface(subsegs, &tmpseg);
16239 ssbond(searchsh, tmpseg);
16240 spivotself(searchsh);
16241 ssbond(searchsh, tmpseg);
16245 spivot(tmpseg, searchsh);
16246 ssdissolve(searchsh);
16247 spivotself(searchsh);
16248 ssdissolve(searchsh);
16249 shellfacedealloc(subsegs, tmpseg.sh);
16253 if (flipstack != NULL) {
16260 if (searchflag)
break;
16262 fnextself(spintet);
16263 if (spintet.tet == searchtet.tet)
break;
16272 for (i = 0; i < missingshs->objects; i++) {
16273 parysh = (face *) fastlookup(missingshs, i);
16275 for (j = 0; j < 3; j++) {
16276 if (isshsubseg(oldsh)) {
16277 sspivot(oldsh, checkseg);
16278 if (sinfected(checkseg)) {
16280 sstpivot1(checkseg, searchtet);
16281 spintet = searchtet;
16283 tssdissolve1(spintet);
16284 fnextself(spintet);
16285 if (spintet.tet == searchtet.tet)
break;
16287 shellfacedealloc(subsegs, checkseg.sh);
16302 for (j = 0; j < missingshbds->objects && (searchflag == -1); j++) {
16303 parysh = (face *) fastlookup(missingshbds, j);
16304 sspivot(*parysh, neighseg);
16305 sstpivot1(neighseg, searchtet);
16308 spintet = searchtet;
16310 pd = apex(spintet);
16311 pe = oppo(spintet);
16313 if ((pd != dummypoint) && (pe != dummypoint)) {
16315 if (!pmarktested(pd) && !pmarktested(pe)) {
16317 for (i = 0; i < missingshs->objects && !interflag; i++) {
16318 parysh = (face *) fastlookup(missingshs, i);
16319 pa = sorg(*parysh);
16320 pb = sdest(*parysh);
16321 pc = sapex(*parysh);
16322 interflag=tri_edge_test(pa, pb, pc, pd, pe, NULL, 1, types, poss);
16323 if (interflag > 0) {
16324 if (interflag == 2) {
16326 if ((types[0] == (
int) ACROSSFACE) ||
16327 (types[0] == (
int) ACROSSEDGE)) {
16329 edestoppo(spintet, crosstet);
16330 if (issubseg(crosstet)) {
16332 report_selfint_face(pa, pb, pc, parysh, &crosstet,
16333 interflag, types, poss);
16335 triface chkface = crosstet;
16337 if (issubface(chkface))
break;
16339 if (chkface.tet == crosstet.tet)
break;
16341 if (issubface(chkface)) {
16343 report_selfint_face(pa, pb, pc, parysh, &chkface,
16344 interflag, types, poss);
16348 ori = orient3d(pa, pb, pc, pd);
16350 esymself(crosstet);
16357 report_selfint_face(pa, pb, pc, parysh, &crosstet,
16358 interflag, types, poss);
16367 if (interflag > 0)
break;
16369 fnextself(spintet);
16370 if (spintet.tet == searchtet.tet)
break;
16400 bool tetgenmesh::formcavity(triface* searchtet, arraypool* missingshs,
16401 arraypool* crosstets, arraypool* topfaces,
16402 arraypool* botfaces, arraypool* toppoints,
16403 arraypool* botpoints)
16405 arraypool *crossedges;
16406 triface spintet, neightet, chkface, *parytet;
16407 face *parysh = NULL;
16408 point pa, pd, pe, *parypt;
16409 bool testflag, invalidflag;
16410 int intflag, types[2], poss[4];
16415 crossedges = topfaces;
16417 if (b->verbose > 2) {
16418 printf(
" Form the cavity of a missing region.\n");
16421 markedge(*searchtet);
16422 crossedges->newindex((
void **) &parytet);
16423 *parytet = *searchtet;
16429 for (i = 0; i < crossedges->objects && !invalidflag; i++) {
16431 searchtet = (triface *) fastlookup(crossedges, i);
16433 pd = org(*searchtet);
16434 if (!pinfected(pd)) {
16436 botpoints->newindex((
void **) &parypt);
16439 pe = dest(*searchtet);
16440 if (!pinfected(pe)) {
16442 toppoints->newindex((
void **) &parypt);
16447 spintet = *searchtet;
16449 if (!infected(spintet)) {
16451 crosstets->newindex((
void **) &parytet);
16452 *parytet = spintet;
16455 fnextself(spintet);
16456 if (spintet.tet == searchtet->tet)
break;
16460 spintet = *searchtet;
16463 pa = apex(spintet);
16464 if (pa != dummypoint) {
16465 if (!pmarktested(pa)) {
16470 for (j = 0; j < 2 && testflag; j++) {
16472 enext(spintet, neightet);
16474 eprev(spintet, neightet);
16477 if (edgemarked(neightet)) {
16482 fnextself(neightet);
16483 if (neightet.tet == spintet.tet)
break;
16491 pe = dest(spintet);
16492 for (k = 0; k < missingshs->objects; k++) {
16493 parysh = (face *) fastlookup(missingshs, k);
16494 intflag = tri_edge_test(sorg(*parysh), sdest(*parysh),
16495 sapex(*parysh), pe, pa, NULL, 1, types, poss);
16498 if (intflag == 2) {
16499 enext(spintet, neightet);
16500 if ((types[0] == (
int) ACROSSFACE) ||
16501 (types[0] == (
int) ACROSSEDGE)) {
16513 intflag = tri_edge_test(sorg(*parysh), sdest(*parysh),
16514 sapex(*parysh), pa, pd, NULL, 1, types, poss);
16517 if (intflag == 2) {
16518 eprev(spintet, neightet);
16519 if ((types[0] == (
int) ACROSSFACE) ||
16520 (types[0] == (
int) ACROSSEDGE)) {
16533 if (k < missingshs->objects) {
16540 esymself(neightet);
16542 if (issubseg(neightet)) {
16543 report_selfint_face(sorg(*parysh), sdest(*parysh),
16544 sapex(*parysh),parysh,&neightet,intflag,types,poss);
16547 chkface = neightet;
16549 if (issubface(chkface))
break;
16551 if (chkface.tet == neightet.tet)
break;
16553 if (issubface(chkface)) {
16555 report_selfint_face(sorg(*parysh), sdest(*parysh),
16556 sapex(*parysh),parysh,&chkface,intflag,types,poss);
16560 markedge(neightet);
16561 crossedges->newindex((
void **) &parytet);
16562 *parytet = neightet;
16572 fnextself(spintet);
16573 if (spintet.tet == searchtet->tet)
break;
16578 for (i = 0; i < crossedges->objects; i++) {
16579 searchtet = (triface *) fastlookup(crossedges, i);
16580 unmarkedge(*searchtet);
16582 crossedges->restart();
16587 for (i = 0; i < crosstets->objects; i++) {
16588 searchtet = (triface *) fastlookup(crosstets, i);
16589 uninfect(*searchtet);
16592 for (i = 0; i < botpoints->objects; i++) {
16593 parypt = (point *) fastlookup(botpoints, i);
16594 puninfect(*parypt);
16596 for (i = 0; i < toppoints->objects; i++) {
16597 parypt = (point *) fastlookup(toppoints, i);
16598 puninfect(*parypt);
16600 crosstets->restart();
16601 botpoints->restart();
16602 toppoints->restart();
16605 i = randomnation(missingshs->objects - 1);
16606 recentsh = * (face *) fastlookup(missingshs, i);
16610 if (b->verbose > 2) {
16611 printf(
" Formed cavity: %ld (%ld) cross tets (edges).\n",
16612 crosstets->objects, crossedges->objects);
16628 for (i = 0; i < crosstets->objects; i++) {
16629 searchtet = (triface *) fastlookup(crosstets, i);
16631 eorgoppo(*searchtet, spintet);
16632 fsym(spintet, neightet);
16633 if (!infected(neightet)) {
16635 topfaces->newindex((
void **) &parytet);
16636 *parytet = neightet;
16638 edestoppo(*searchtet, spintet);
16639 fsym(spintet, neightet);
16640 if (!infected(neightet)) {
16642 botfaces->newindex((
void **) &parytet);
16643 *parytet = neightet;
16646 pa = org(neightet);
16647 if (!pinfected(pa)) {
16648 if (pa != dummypoint) {
16650 botpoints->newindex((
void **) &parypt);
16652 toppoints->newindex((
void **) &parypt);
16656 pa = dest(neightet);
16657 if (!pinfected(pa)) {
16658 if (pa != dummypoint) {
16660 botpoints->newindex((
void **) &parypt);
16662 toppoints->newindex((
void **) &parypt);
16669 for (i = 0; i < toppoints->objects; i++) {
16670 parypt = (point *) fastlookup(toppoints, i);
16671 puninfect(*parypt);
16673 for (i = 0; i < botpoints->objects; i++) {
16674 parypt = (point *) fastlookup(botpoints, i);
16675 puninfect(*parypt);
16699 void tetgenmesh::delaunizecavity(arraypool *cavpoints, arraypool *cavfaces,
16700 arraypool *cavshells, arraypool *newtets,
16701 arraypool *crosstets, arraypool *misfaces)
16703 triface searchtet, neightet, *parytet, *parytet1;
16704 face tmpsh, *parysh;
16705 point pa, pb, pc, pd, pt[3], *parypt;
16706 insertvertexflags ivf;
16708 long baknum, bakhullsize;
16709 int bakchecksubsegflag, bakchecksubfaceflag;
16713 if (b->verbose > 2) {
16714 printf(
" Delaunizing cavity: %ld points, %ld faces.\n",
16715 cavpoints->objects, cavfaces->objects);
16718 baknum = crosstets->objects;
16719 bakhullsize = hullsize;
16720 bakchecksubsegflag = checksubsegflag;
16721 bakchecksubfaceflag = checksubfaceflag;
16723 checksubsegflag = 0;
16724 checksubfaceflag = 0;
16731 pa = pb = pc = NULL;
16732 for (i = 0; i < cavfaces->objects; i++) {
16733 parytet = (triface *) fastlookup(cavfaces, i);
16734 parytet->ver = epivot[parytet->ver];
16735 if (apex(*parytet) != dummypoint) {
16736 pa = org(*parytet);
16737 pb = dest(*parytet);
16738 pc = apex(*parytet);
16743 for (; i < cavfaces->objects; i++) {
16744 parytet = (triface *) fastlookup(cavfaces, i);
16745 pt[0] = org(*parytet);
16746 pt[1] = dest(*parytet);
16747 pt[2] = apex(*parytet);
16748 for (j = 0; j < 3; j++) {
16749 if (pt[j] != dummypoint) {
16750 ori = orient3d(pa, pb, pc, pt[j]);
16754 pt[j] = pa; pa = pb; pb = pt[j];
16760 if (pd != NULL)
break;
16764 initialdelaunay(pa, pb, pc, pd);
16767 for (i = 0; i < cavpoints->objects; i++) {
16768 pt[0] = * (point *) fastlookup(cavpoints, i);
16769 searchtet = recenttet;
16770 ivf.iloc = (int) OUTSIDE;
16771 insertpoint(pt[0], &searchtet, NULL, NULL, &ivf);
16774 if (b->verbose > 2) {
16775 printf(
" Identifying %ld boundary faces of the cavity.\n",
16776 cavfaces->objects);
16782 for (i = 0; i < cavfaces->objects; i++) {
16783 parytet = (triface *) fastlookup(cavfaces, i);
16785 if (infected(*parytet))
continue;
16786 parytet->ver = epivot[parytet->ver];
16787 pt[0] = org(*parytet);
16788 pt[1] = dest(*parytet);
16789 pt[2] = apex(*parytet);
16791 makeshellface(subfaces, &tmpsh);
16792 setshvertices(tmpsh, pt[0], pt[1], pt[2]);
16794 searchtet.tet = NULL;
16795 if (scoutsubface(&tmpsh, &searchtet, 0)) {
16799 tmpsh.sh[0] = (shellface) encode(*parytet);
16801 cavshells->newindex((
void **) &parysh);
16806 shellfacedealloc(subfaces, tmpsh.sh);
16808 misfaces->newindex((
void **) &parytet1);
16809 *parytet1 = *parytet;
16813 if (misfaces->objects > 0) {
16814 if (b->verbose > 2) {
16815 printf(
" Enlarging the cavity. %ld missing bdry faces\n",
16816 misfaces->objects);
16820 for (i = 0; i < cavshells->objects; i++) {
16821 parysh = (face *) fastlookup(cavshells, i);
16822 stpivot(*parysh, neightet);
16823 tsdissolve(neightet);
16824 fsymself(neightet);
16825 tsdissolve(neightet);
16826 shellfacedealloc(subfaces, parysh->sh);
16828 cavshells->restart();
16831 for (i = 0; i < cavpoints->objects; i++) {
16832 pt[0] = * (point *) fastlookup(cavpoints, i);
16837 for (i = 0; i < misfaces->objects; i++) {
16839 parytet = (triface *) fastlookup(misfaces, i);
16840 if (!infected(*parytet)) {
16843 crosstets->newindex((
void **) &parytet1);
16844 *parytet1 = *parytet;
16846 pd = oppo(*parytet);
16847 if (!pinfected(pd)) {
16848 searchtet = recenttet;
16849 ivf.iloc = (int) OUTSIDE;
16850 insertpoint(pd, &searchtet, NULL, NULL, &ivf);
16852 cavpoints->newindex((
void **) &parypt);
16856 for (j = 0; j < 3; j++) {
16857 esym(*parytet, neightet);
16858 fsymself(neightet);
16859 if (!infected(neightet)) {
16860 cavfaces->newindex((
void **) &parytet1);
16861 *parytet1 = neightet;
16863 enextself(*parytet);
16869 for (i = 0; i < cavpoints->objects; i++) {
16870 pt[0] = * (point *) fastlookup(cavpoints, i);
16874 misfaces->restart();
16883 marktest(recenttet);
16884 newtets->newindex((
void **) &parytet);
16885 *parytet = recenttet;
16886 for (i = 0; i < newtets->objects; i++) {
16887 searchtet = * (triface *) fastlookup(newtets, i);
16888 for (j = 0; j < 4; j++) {
16889 decode(searchtet.tet[j], neightet);
16890 if (!marktested(neightet)) {
16891 marktest(neightet);
16892 newtets->newindex((
void **) &parytet);
16893 *parytet = neightet;
16898 cavpoints->restart();
16899 cavfaces->restart();
16901 if (crosstets->objects > baknum) {
16907 hullsize = bakhullsize;
16908 checksubsegflag = bakchecksubsegflag;
16909 checksubfaceflag = bakchecksubfaceflag;
16927 bool tetgenmesh::fillcavity(arraypool* topshells, arraypool* botshells,
16928 arraypool* midfaces, arraypool* missingshs,
16929 arraypool* topnewtets, arraypool* botnewtets,
16930 triface* crossedge)
16932 arraypool *cavshells;
16933 triface bdrytet, neightet, *parytet;
16934 triface searchtet, spintet;
16944 for (j = 0; j < 2; j++) {
16945 cavshells = (j == 0 ? topshells : botshells);
16946 if (cavshells != NULL) {
16947 for (i = 0; i < cavshells->objects; i++) {
16949 parysh = (face *) fastlookup(cavshells, i);
16951 decode(parysh->sh[0], bdrytet);
16953 pb = dest(bdrytet);
16954 pc = apex(bdrytet);
16956 stpivot(*parysh, neightet);
16960 bond(bdrytet, neightet);
16961 tsdissolve(neightet);
16963 setpoint2tet(pa, (tetrahedron) neightet.tet);
16964 setpoint2tet(pb, (tetrahedron) neightet.tet);
16965 setpoint2tet(pc, (tetrahedron) neightet.tet);
16970 if (crossedge != NULL) {
16972 triface toptet, bottet, spintet, *midface;
16975 int types[2], poss[4];
16980 pd = org(*crossedge);
16981 pe = dest(*crossedge);
16988 for (i = 0; i < topnewtets->objects && !mflag; i++) {
16989 searchtet = * (triface *) fastlookup(topnewtets, i);
16990 for (searchtet.ver = 0; searchtet.ver < 4 && !mflag; searchtet.ver++) {
16991 pa = org(searchtet);
16992 if (pmarktested(pa)) {
16993 pb = dest(searchtet);
16994 if (pmarktested(pb)) {
16995 pc = apex(searchtet);
16996 if (pmarktested(pc)) {
16998 interflag = tri_edge_test(pa,pb,pc,pd,pe,NULL,1,types,poss);
16999 if (interflag == 2) {
17001 toptet = searchtet;
17004 ori = orient3d(pa, pb, pc, pd);
17009 }
else if (ori == 0) {
17010 terminatetetgen(
this, 2);
17013 for (j = 0; j < botnewtets->objects; j++) {
17014 neightet = * (triface *) fastlookup(botnewtets, j);
17016 if ((point) neightet.tet[4] == pb) {
17018 }
else if ((point) neightet.tet[5] == pb) {
17020 }
else if ((point) neightet.tet[6] == pb) {
17022 }
else if ((point) neightet.tet[7] == pb) {
17028 if (dest(neightet) == pa) {
17030 }
else if (apex(neightet) == pa) {
17031 eprevesymself(neightet);
17032 }
else if (oppo(neightet) == pa) {
17033 esymself(neightet);
17034 enextself(neightet);
17039 if (apex(neightet) == pc) {
17054 bond(toptet, bottet);
17060 midfaces->newindex((
void **) &parytet);
17066 i = randomnation(missingshs->objects - 1);
17067 recentsh = * (face *) fastlookup(missingshs, i);
17071 for (i = 0; i < midfaces->objects && mflag; i++) {
17073 midface = (triface *) fastlookup(midfaces, i);
17075 for (j = 0; j < 3 && mflag; j++) {
17082 if (pmarktested(pc)) {
17085 if (pc == dummypoint) {
17086 terminatetetgen(
this, 2);
17092 if (!marktested(toptet)) {
17094 bflag =
true;
break;
17098 if (!facemarked(toptet)) {
17099 fsym(*midface, bottet);
17104 if (pd == pc)
break;
17106 if (bottet.tet == spintet.tet) {
17113 if (marktested(bottet)) {
17115 bond(toptet, bottet);
17121 midfaces->newindex((
void **) &parytet);
17126 terminatetetgen(
this, 2);
17130 fsym(*midface, bottet);
17135 if (pmarktested(pd)) {
17140 ori = orient3d(dest(toptet), pc, oppo(toptet), pd);
17145 }
else if (ori > 0) {
17151 terminatetetgen(
this, 2);
17160 enextself(*midface);
17165 if (b->verbose > 2) {
17166 printf(
" Found %ld middle subfaces.\n", midfaces->objects);
17168 face oldsh, newsh, casout, casin, neighsh;
17170 oldsh = * (face *) fastlookup(missingshs, 0);
17173 for (i = 0; i < midfaces->objects; i++) {
17175 midface = (triface *) fastlookup(midfaces, i);
17176 unmarkface(*midface);
17177 makeshellface(subfaces, &newsh);
17178 setsorg(newsh, org(*midface));
17179 setsdest(newsh, dest(*midface));
17180 setsapex(newsh, apex(*midface));
17182 setshellmark(newsh, shellmark(oldsh));
17183 if (checkconstraints) {
17184 setareabound(newsh, areabound(oldsh));
17186 if (useinsertradius) {
17187 setfacetindex(newsh, getfacetindex(oldsh));
17190 tsbond(*midface, newsh);
17191 fsym(*midface, neightet);
17193 tsbond(neightet, newsh);
17198 for (i = 0; i < midfaces->objects; i++) {
17200 midface = (triface *) fastlookup(midfaces, i);
17201 for (j = 0; j < 3; j++) {
17202 tspivot(*midface, newsh);
17203 spivot(newsh, casout);
17204 if (casout.sh == NULL) {
17206 fnext(*midface, searchtet);
17209 tsspivot1(searchtet, checkseg);
17210 if (checkseg.sh != NULL) {
17213 checkseg.shver = 0;
17214 spivot(checkseg, oldsh);
17215 if (sinfected(checkseg)) {
17217 spintet = searchtet;
17219 tssdissolve1(spintet);
17220 fnextself(spintet);
17221 if (spintet.tet == searchtet.tet)
break;
17223 shellfacedealloc(subsegs, checkseg.sh);
17225 checkseg.sh = NULL;
17227 spivot(oldsh, casout);
17228 if (casout.sh != NULL) {
17230 if (checkseg.sh != NULL) {
17233 checkseg.shver = 0;
17234 if (sorg(newsh) != sorg(checkseg)) {
17237 spivot(casin, neighsh);
17238 while (neighsh.sh != oldsh.sh) {
17240 spivot(casin, neighsh);
17243 sbond1(newsh, casout);
17244 sbond1(casin, newsh);
17246 if (checkseg.sh != NULL) {
17247 ssbond(newsh, checkseg);
17252 tspivot(searchtet, neighsh);
17253 if (neighsh.sh != NULL) {
17255 sbond(newsh, neighsh);
17258 fnextself(searchtet);
17261 enextself(*midface);
17266 for (i = 0; i < missingshs->objects; i++) {
17267 parysh = (face *) fastlookup(missingshs, i);
17268 shellfacedealloc(subfaces, parysh->sh);
17271 if (toptet.tet != NULL) {
17283 for (i = 1; i < missingshs->objects; i++) {
17284 parysh = (face *) fastlookup(missingshs, i);
17285 if (((sorg(*parysh) == pa) && (sdest(*parysh) == pb)) ||
17286 ((sorg(*parysh) == pb) && (sdest(*parysh) == pa)))
break;
17287 if (((sorg(*parysh) == pc) && (sdest(*parysh) == pd)) ||
17288 ((sorg(*parysh) == pd) && (sdest(*parysh) == pc)))
break;
17290 if (i < missingshs->objects) {
17292 recentsh = *parysh;
17294 terminatetetgen(
this, 2);
17301 midfaces->restart();
17307 for (j = 0; j < 2; j++) {
17308 cavshells = (j == 0 ? topshells : botshells);
17309 if (cavshells != NULL) {
17310 for (i = 0; i < cavshells->objects; i++) {
17311 parysh = (face *) fastlookup(cavshells, i);
17312 shellfacedealloc(subfaces, parysh->sh);
17317 topshells->restart();
17318 if (botshells != NULL) {
17319 botshells->restart();
17331 void tetgenmesh::carvecavity(arraypool *crosstets, arraypool *topnewtets,
17332 arraypool *botnewtets)
17334 arraypool *newtets;
17335 shellface *sptr, *ssptr;
17336 triface *parytet, *pnewtet, newtet, neightet, spintet;
17337 face checksh, *parysh;
17338 face checkseg, *paryseg;
17342 if (b->verbose > 2) {
17343 printf(
" Carve cavity: %ld old tets.\n", crosstets->objects);
17354 for (i = 0; i < crosstets->objects; i++) {
17355 parytet = (triface *) fastlookup(crosstets, i);
17356 if ((sptr = (shellface*) parytet->tet[9]) != NULL) {
17357 for (j = 0; j < 4; j++) {
17359 sdecode(sptr[j], checksh);
17360 if (!sinfected(checksh)) {
17362 cavetetshlist->newindex((
void **) &parysh);
17368 if ((ssptr = (shellface*) parytet->tet[8]) != NULL) {
17369 for (j = 0; j < 6; j++) {
17371 sdecode(ssptr[j], checkseg);
17373 if (checkseg.sh[3] != NULL) {
17374 if (!sinfected(checkseg)) {
17376 cavetetseglist->newindex((
void **) &paryseg);
17377 *paryseg = checkseg;
17386 for (i = 0; i < cavetetshlist->objects; i++) {
17387 parysh = (face *) fastlookup(cavetetshlist, i);
17388 suninfect(*parysh);
17391 for (i = 0; i < cavetetseglist->objects; i++) {
17392 paryseg = (face *) fastlookup(cavetetseglist, i);
17393 suninfect(*paryseg);
17397 for (i = 0; i < cavetetshlist->objects; i++) {
17398 parysh = (face *) fastlookup(cavetetshlist, i);
17400 stpivot(*parysh, neightet);
17402 if (infected(neightet)) {
17404 sesymself(*parysh);
17405 stpivot(*parysh, neightet);
17407 if (infected(neightet)) {
17409 stdissolve(checksh);
17410 caveencshlist->newindex((
void **) &parysh);
17414 if (!infected(neightet)) {
17416 fsym(neightet, newtet);
17417 sesymself(*parysh);
17418 tsbond(newtet, *parysh);
17423 for (i = 0; i < cavetetseglist->objects; i++) {
17424 checkseg = * (face *) fastlookup(cavetetseglist, i);
17426 sstpivot1(checkseg, neightet);
17427 spintet = neightet;
17429 if (!infected(spintet)) {
17433 fnextself(spintet);
17434 if (spintet.tet == neightet.tet) {
17435 sstdissolve1(checkseg);
17436 caveencseglist->newindex((
void **) &paryseg);
17437 *paryseg = checkseg;
17441 if (!infected(spintet)) {
17443 sstbond1(checkseg, spintet);
17444 neightet = spintet;
17446 tssbond1(spintet, checkseg);
17447 fnextself(spintet);
17448 if (spintet.tet == neightet.tet)
break;
17454 cavetetshlist->restart();
17455 cavetetseglist->restart();
17458 for (i = 0; i < crosstets->objects; i++) {
17459 parytet = (triface *) fastlookup(crosstets, i);
17460 if (ishulltet(*parytet)) {
17463 tetrahedrondealloc(parytet->tet);
17466 crosstets->restart();
17470 for (j = 0; j < 2; j++) {
17471 newtets = (j == 0 ? topnewtets : botnewtets);
17472 if (newtets != NULL) {
17473 for (i = 0; i < newtets->objects; i++) {
17474 parytet = (triface *) fastlookup(newtets, i);
17475 if (infected(*parytet)) {
17476 crosstets->newindex((
void **) &pnewtet);
17477 *pnewtet = *parytet;
17484 for (i = 0; i < crosstets->objects; i++) {
17485 parytet = (triface *) fastlookup(crosstets, i);
17486 for (j = 0; j < 4; j++) {
17487 decode(parytet->tet[j], neightet);
17488 if (marktested(neightet)) {
17489 if (!infected(neightet)) {
17493 crosstets->newindex((
void **) &pnewtet);
17494 *pnewtet = neightet;
17500 parytet = (triface *) fastlookup(crosstets, 0);
17501 recenttet = *parytet;
17504 for (j = 0; j < 2; j++) {
17505 newtets = (j == 0 ? topnewtets : botnewtets);
17506 if (newtets != NULL) {
17507 for (i = 0; i < newtets->objects; i++) {
17508 parytet = (triface *) fastlookup(newtets, i);
17509 if (infected(*parytet)) {
17511 uninfect(*parytet);
17512 unmarktest(*parytet);
17513 if (ishulltet(*parytet)) {
17518 tetrahedrondealloc(parytet->tet);
17524 crosstets->restart();
17525 topnewtets->restart();
17526 if (botnewtets != NULL) {
17527 botnewtets->restart();
17537 void tetgenmesh::restorecavity(arraypool *crosstets, arraypool *topnewtets,
17538 arraypool *botnewtets, arraypool *missingshbds)
17540 triface *parytet, neightet, spintet;
17548 for (i = 0; i < crosstets->objects; i++) {
17549 parytet = (triface *) fastlookup(crosstets, i);
17551 for (parytet->ver = 0; parytet->ver < 4; parytet->ver++) {
17552 fsym(*parytet, neightet);
17553 if (!infected(neightet)) {
17555 bond(*parytet, neightet);
17560 ppt = (point *) &(parytet->tet[4]);
17561 for (j = 0; j < 4; j++) {
17562 setpoint2tet(ppt[j], encode(*parytet));
17567 for (i = 0; i < crosstets->objects; i++) {
17568 parytet = (triface *) fastlookup(crosstets, i);
17569 uninfect(*parytet);
17573 if (crosstets->objects > 0) {
17574 recenttet = * (triface *) fastlookup(crosstets, 0);
17578 for (i = 0; i < missingshbds->objects; i++) {
17579 parysh = (face *) fastlookup(missingshbds, i);
17580 sspivot(*parysh, checkseg);
17581 if (checkseg.sh[3] != NULL) {
17582 if (sinfected(checkseg)) {
17584 sstpivot1(checkseg, neightet);
17585 spintet = neightet;
17587 tssdissolve1(spintet);
17588 fnextself(spintet);
17589 if (spintet.tet == neightet.tet)
break;
17591 shellfacedealloc(subsegs, checkseg.sh);
17592 ssdissolve(*parysh);
17599 for (i = 0; i < topnewtets->objects; i++) {
17600 parytet = (triface *) fastlookup(topnewtets, i);
17601 tetrahedrondealloc(parytet->tet);
17604 if (botnewtets != NULL) {
17605 for (i = 0; i < botnewtets->objects; i++) {
17606 parytet = (triface *) fastlookup(botnewtets, i);
17607 tetrahedrondealloc(parytet->tet);
17611 crosstets->restart();
17612 topnewtets->restart();
17613 if (botnewtets != NULL) {
17614 botnewtets->restart();
17627 void tetgenmesh::flipcertify(triface *chkface,badface **pqueue,point plane_pa,
17628 point plane_pb, point plane_pc)
17630 badface *parybf, *prevbf, *nextbf;
17640 fsym(*chkface, neightet);
17642 p[0] = org(*chkface);
17643 p[1] = dest(*chkface);
17644 p[2] = apex(*chkface);
17645 p[3] = oppo(*chkface);
17646 p[4] = oppo(neightet);
17650 for (i = 0; i < 3; i++) {
17651 if (pmarktest2ed(p[i])) topi++;
17652 if (pmarktest3ed(p[i])) boti++;
17654 if ((topi == 0) || (boti == 0)) {
17657 for (i = 3; i < 5; i++) {
17658 if (pmarktest2ed(p[i])) topi++;
17659 if (pmarktest3ed(p[i])) boti++;
17661 if ((topi == 0) || (boti == 0)) {
17664 if ((p[3] != dummypoint) && (p[4] != dummypoint)) {
17666 tspivot(*chkface, checksh);
17667 if (checksh.sh == NULL) {
17668 insph = insphere_s(p[1], p[0], p[2], p[3], p[4]);
17671 if (b->verbose > 2) {
17672 printf(
" A locally non-Delanay face (%d, %d, %d)-%d,%d\n",
17673 pointmark(p[0]), pointmark(p[1]), pointmark(p[2]),
17674 pointmark(p[3]), pointmark(p[4]));
17676 parybf = (badface *) flippool->alloc();
17678 parybf->tt = *chkface;
17679 parybf->forg = p[0];
17680 parybf->fdest = p[1];
17681 parybf->fapex = p[2];
17682 parybf->foppo = p[3];
17683 parybf->noppo = p[4];
17685 if (*pqueue == NULL) {
17687 parybf->nextitem = NULL;
17689 parybf->nextitem = *pqueue;
17700 for (i = 0; i < 5; i++) {
17701 if (pmarktest2ed(p[i])) {
17703 w[i] = orient3dfast(plane_pa, plane_pb, plane_pc, p[i]);
17704 if (w[i] < 0) w[i] = -w[i];
17710 insph = insphere(p[1], p[0], p[2], p[3], p[4]);
17711 ori4 = orient4d(p[1], p[0], p[2], p[3], p[4], w[1], w[0], w[2], w[3], w[4]);
17714 if (b->verbose > 2) {
17715 printf(
" Insert face (%d, %d, %d) - %d, %d\n", pointmark(p[0]),
17716 pointmark(p[1]), pointmark(p[2]), pointmark(p[3]), pointmark(p[4]));
17719 parybf = (badface *) flippool->alloc();
17721 parybf->key = -insph / ori4;
17722 parybf->tt = *chkface;
17723 parybf->forg = p[0];
17724 parybf->fdest = p[1];
17725 parybf->fapex = p[2];
17726 parybf->foppo = p[3];
17727 parybf->noppo = p[4];
17731 if (*pqueue == NULL) {
17733 parybf->nextitem = NULL;
17740 while (nextbf != NULL) {
17741 if (nextbf->key < parybf->key) {
17743 nextbf = nextbf->nextitem;
17750 if (prevbf == NULL) {
17753 prevbf->nextitem = parybf;
17755 parybf->nextitem = nextbf;
17757 }
else if (ori4 == 0) {
17776 void tetgenmesh::flipinsertfacet(arraypool *crosstets, arraypool *toppoints,
17777 arraypool *botpoints, arraypool *midpoints)
17779 arraypool *crossfaces, *bfacearray;
17780 triface fliptets[6], baktets[2], fliptet, newface;
17781 triface neightet, *parytet;
17783 badface *popbf, bface;
17784 point plane_pa, plane_pb, plane_pc;
17785 point p1, p2, pd, pe;
17787 flipconstraints fc;
17789 int convcount, copcount;
17790 int flipflag, fcount;
17792 long f23count, f32count, f44count;
17795 f23count = flip23count;
17796 f32count = flip32count;
17797 f44count = flip44count;
17800 calculateabovepoint(midpoints, &plane_pa, &plane_pb, &plane_pc);
17803 for (i = 0; i < toppoints->objects; i++) {
17804 parypt = (point *) fastlookup(toppoints, i);
17805 if (!pmarktested(*parypt)) {
17806 pmarktest2(*parypt);
17809 for (i = 0; i < botpoints->objects; i++) {
17810 parypt = (point *) fastlookup(botpoints, i);
17811 if (!pmarktested(*parypt)) {
17812 pmarktest3(*parypt);
17817 crossfaces = cavetetlist;
17821 for (i = 0; i < crosstets->objects; i++) {
17822 parytet = (triface *) fastlookup(crosstets, i);
17823 fliptet = *parytet;
17824 for (fliptet.ver = 0; fliptet.ver < 4; fliptet.ver++) {
17825 fsym(fliptet, neightet);
17826 if (infected(neightet)) {
17827 if (!marktested(neightet)) {
17828 crossfaces->newindex((
void **) &parytet);
17829 *parytet = fliptet;
17836 if (b->verbose > 1) {
17837 printf(
" Found %ld crossing faces.\n", crossfaces->objects);
17840 for (i = 0; i < crosstets->objects; i++) {
17841 parytet = (triface *) fastlookup(crosstets, i);
17842 unmarktest(*parytet);
17843 uninfect(*parytet);
17849 for (i = 0; i < crossfaces->objects; i++) {
17850 parytet = (triface *) fastlookup(crossfaces, i);
17851 flipcertify(parytet, &pqueue, plane_pa, plane_pb, plane_pc);
17853 crossfaces->restart();
17856 bfacearray =
new arraypool(
sizeof(triface), 4);
17862 while (pqueue != NULL) {
17868 pqueue = pqueue->nextitem;
17870 flippool->dealloc((
void *) popbf);
17872 if (!isdeadtet(bface.tt)) {
17873 if ((org(bface.tt) == bface.forg) && (dest(bface.tt) == bface.fdest) &&
17874 (apex(bface.tt) == bface.fapex) && (oppo(bface.tt) == bface.foppo)) {
17876 fliptet = bface.tt;
17877 fsym(fliptet, neightet);
17878 if (oppo(neightet) == bface.noppo) {
17879 pd = oppo(fliptet);
17880 pe = oppo(neightet);
17882 if (b->verbose > 2) {
17883 printf(
" Get face (%d, %d, %d) - %d, %d, tau = %.17g\n",
17884 pointmark(bface.forg), pointmark(bface.fdest),
17885 pointmark(bface.fapex), pointmark(bface.foppo),
17886 pointmark(bface.noppo), bface.key);
17893 for (i = 0; i < 3; i++) {
17895 p2 = dest(fliptet);
17896 ori[i] = orient3d(p1, p2, pd, pe);
17900 }
else if (ori[i] == 0) {
17905 enextself(fliptet);
17908 if (convcount == 3) {
17910 fliptets[0] = fliptet;
17911 fliptets[1] = neightet;
17912 flip23(fliptets, 1, &fc);
17914 for (i = 0; i < 3; i++) {
17915 eprevesym(fliptets[i], newface);
17916 crossfaces->newindex((
void **) &parytet);
17917 *parytet = newface;
17919 for (i = 0; i < 3; i++) {
17920 enextesym(fliptets[i], newface);
17921 crossfaces->newindex((
void **) &parytet);
17922 *parytet = newface;
17925 }
else if (convcount == 2) {
17929 for (i = 0; i < 3; i++) {
17930 if (ori[i] <= 0)
break;
17931 enextself(fliptet);
17935 esym(fliptet, fliptets[0]);
17938 p1 = apex(fliptets[n]);
17939 if (!(pmarktested(p1) || pmarktest2ed(p1) || pmarktest3ed(p1))) {
17944 fnext(fliptets[n], fliptets[n + 1]);
17946 }
while ((fliptets[n].tet != fliptet.tet) && (n < 5));
17950 flip32(fliptets, 1, &fc);
17952 for (i = 0; i < 3; i++) {
17953 esym(fliptets[0], newface);
17954 crossfaces->newindex((
void **) &parytet);
17955 *parytet = newface;
17956 enextself(fliptets[0]);
17958 for (i = 0; i < 3; i++) {
17959 esym(fliptets[1], newface);
17960 crossfaces->newindex((
void **) &parytet);
17961 *parytet = newface;
17962 enextself(fliptets[1]);
17965 }
else if (n == 4) {
17966 if (copcount == 1) {
17979 fliptets[0] = fliptet;
17981 baktets[0] = fliptets[2];
17982 baktets[1] = fliptets[3];
17984 flip23(fliptets, 1, &fc);
17988 for (i = 1; i < 3; i++) {
17989 eprevesym(fliptets[i], newface);
17990 crossfaces->newindex((
void **) &parytet);
17991 *parytet = newface;
17993 for (i = 1; i < 3; i++) {
17994 enextesym(fliptets[i], newface);
17995 crossfaces->newindex((
void **) &parytet);
17996 *parytet = newface;
17999 enextesymself(fliptets[0]);
18000 eprevself(fliptets[0]);
18001 fliptets[1] = baktets[0];
18002 fliptets[2] = baktets[1];
18003 flip32(fliptets, 1, &fc);
18008 enextself(fliptets[0]);
18009 for (i = 1; i < 3; i++) {
18010 esym(fliptets[0], newface);
18011 crossfaces->newindex((
void **) &parytet);
18012 *parytet = newface;
18013 enextself(fliptets[0]);
18015 enextself(fliptets[1]);
18016 for (i = 1; i < 3; i++) {
18017 esym(fliptets[1], newface);
18018 crossfaces->newindex((
void **) &parytet);
18019 *parytet = newface;
18020 enextself(fliptets[1]);
18031 if (b->verbose > 2) {
18032 printf(
" Ignore face (%d, %d, %d) - %d, %d, tau = %.17g\n",
18033 pointmark(bface.forg), pointmark(bface.fdest),
18034 pointmark(bface.fapex), pointmark(bface.foppo),
18035 pointmark(bface.noppo), bface.key);
18039 if (flipflag == 1) {
18041 for (i = 0; i < crossfaces->objects; i++) {
18042 parytet = (triface *) fastlookup(crossfaces, i);
18043 flipcertify(parytet, &pqueue, plane_pa, plane_pb, plane_pc);
18045 crossfaces->restart();
18048 for (i = 0; i < bfacearray->objects; i++) {
18049 parytet = (triface *) fastlookup(bfacearray, i);
18051 if (!isdeadtet(*parytet)) {
18052 flipcertify(parytet, &pqueue, plane_pa, plane_pb, plane_pc);
18055 bfacearray->restart();
18058 }
else if (flipflag == 0) {
18060 bfacearray->newindex((
void **) &parytet);
18061 *parytet = fliptet;
18069 if (bfacearray->objects > 0) {
18071 printf(
"!! No flip is found in %ld faces.\n", bfacearray->objects);
18072 terminatetetgen(
this, 2);
18079 for (i = 0; i < toppoints->objects; i++) {
18080 parypt = (point *) fastlookup(toppoints, i);
18081 punmarktest2(*parypt);
18083 for (i = 0; i < botpoints->objects; i++) {
18084 parypt = (point *) fastlookup(botpoints, i);
18085 punmarktest3(*parypt);
18088 f23count = flip23count - f23count;
18089 f32count = flip32count - f32count;
18090 f44count = flip44count - f44count;
18091 totalfcount = f23count + f32count + f44count;
18092 if (b->verbose > 2) {
18093 printf(
" Total %ld flips. f23(%ld), f32(%ld), f44(%ld).\n",
18094 totalfcount, f23count, f32count, f44count);
18104 int tetgenmesh::insertpoint_cdt(point newpt, triface *searchtet, face *splitsh,
18105 face *splitseg, insertvertexflags *ivf,
18106 arraypool *cavpoints, arraypool *cavfaces,
18107 arraypool *cavshells, arraypool *newtets,
18108 arraypool *crosstets, arraypool *misfaces)
18110 triface neightet, *parytet;
18111 face checksh, *parysh, *parysh1;
18112 face *paryseg, *paryseg1;
18117 if (b->verbose > 2) {
18118 printf(
" Insert point %d into CDT\n", pointmark(newpt));
18121 if (!insertpoint(newpt, searchtet, NULL, NULL, ivf)) {
18127 for (i = 0; i < cavetetvertlist->objects; i++) {
18128 cavpoints->newindex((
void **) &parypt);
18129 *parypt = * (point *) fastlookup(cavetetvertlist, i);
18132 cavpoints->newindex((
void **) &parypt);
18135 for (i = 0; i < cavebdrylist->objects; i++) {
18136 cavfaces->newindex((
void **) &parytet);
18137 *parytet = * (triface *) fastlookup(cavebdrylist, i);
18140 for (i = 0; i < caveoldtetlist->objects; i++) {
18141 crosstets->newindex((
void **) &parytet);
18142 *parytet = * (triface *) fastlookup(caveoldtetlist, i);
18145 cavetetvertlist->restart();
18146 cavebdrylist->restart();
18147 caveoldtetlist->restart();
18150 delaunizecavity(cavpoints, cavfaces, cavshells, newtets, crosstets,
18152 fillcavity(cavshells, NULL, NULL, NULL, NULL, NULL, NULL);
18153 carvecavity(crosstets, newtets, NULL);
18155 if ((splitsh != NULL) || (splitseg != NULL)) {
18157 sinsertvertex(newpt, splitsh, splitseg, ivf->sloc, ivf->sbowywat, 0);
18160 for (i = 0; i < caveshbdlist->objects; i++) {
18162 parysh = (face *) fastlookup(caveshbdlist, i);
18163 spivot(*parysh, checksh);
18165 if (checksh.sh[3] != NULL) {
18166 subfacstack->newindex((
void **) &parysh);
18171 if (splitseg != NULL) {
18173 for (i = 0; i < cavesegshlist->objects; i++) {
18174 paryseg = (face *) fastlookup(cavesegshlist, i);
18175 subsegstack->newindex((
void **) &paryseg1);
18176 *paryseg1 = *paryseg;
18181 for (i = 0; i < caveshlist->objects; i++) {
18182 parysh = (face *) fastlookup(caveshlist, i);
18183 if (checksubfaceflag) {
18187 stpivot(*parysh, neightet);
18188 if (neightet.tet != NULL) {
18189 if (neightet.tet[4] != NULL) {
18191 tsdissolve(neightet);
18192 fsymself(neightet);
18193 tsdissolve(neightet);
18197 shellfacedealloc(subfaces, parysh->sh);
18199 if (splitseg != NULL) {
18201 shellfacedealloc(subsegs, splitseg->sh);
18205 caveshlist->restart();
18206 caveshbdlist->restart();
18207 cavesegshlist->restart();
18213 for (i = 0; i < caveencshlist->objects; i++) {
18214 parysh = (face *) fastlookup(caveencshlist, i);
18215 if (parysh->sh[3] != NULL) {
18216 subfacstack->newindex((
void **) &parysh1);
18217 *parysh1 = *parysh;
18224 for (i = 0; i < caveencseglist->objects; i++) {
18225 paryseg = (face *) fastlookup(caveencseglist, i);
18226 if (paryseg->sh[3] != NULL) {
18227 subsegstack->newindex((
void **) &paryseg1);
18228 *paryseg1 = *paryseg;
18232 caveencshlist->restart();
18233 caveencseglist->restart();
18249 void tetgenmesh::refineregion(face &splitsh, arraypool *cavpoints,
18250 arraypool *cavfaces, arraypool *cavshells,
18251 arraypool *newtets, arraypool *crosstets,
18252 arraypool *misfaces)
18254 triface searchtet, spintet;
18255 face splitseg, *paryseg;
18256 point steinpt, pa, pb, refpt;
18257 insertvertexflags ivf;
18258 enum interresult dir;
18259 long baknum = points->items;
18264 for (i = 0; i < 3; i++) {
18265 sspivot(splitsh, splitseg);
18266 if (splitseg.sh == NULL)
break;
18267 senextself(splitsh);
18270 if (b->verbose > 2) {
18271 printf(
" Refining region at edge (%d, %d, %d).\n",
18272 pointmark(sorg(splitsh)), pointmark(sdest(splitsh)),
18273 pointmark(sapex(splitsh)));
18277 pa = sorg(splitsh);
18278 pb = sdest(splitsh);
18280 makepoint(&steinpt, FREEFACETVERTEX);
18281 for (i = 0; i < 3; i++) {
18282 steinpt[i] = 0.5 * (pa[i] + pb[i]);
18287 ivf.sloc = (int) ONEDGE;
18289 ivf.assignmeshsize = b->metric;
18290 ivf.smlenflag = useinsertradius;
18292 point2tetorg(pa, searchtet);
18293 ivf.iloc = (int) OUTSIDE;
18296 if (!insertpoint_cdt(steinpt, &searchtet, &splitsh, NULL, &ivf, cavpoints,
18297 cavfaces, cavshells, newtets, crosstets, misfaces)) {
18298 if (ivf.iloc == (
int) ENCSEGMENT) {
18299 pointdealloc(steinpt);
18301 i = randomnation(encseglist->objects);
18302 paryseg = (face *) fastlookup(encseglist, i);
18303 splitseg = *paryseg;
18304 encseglist->restart();
18307 pa = sorg(splitseg);
18308 pb = sdest(splitseg);
18310 makepoint(&steinpt, FREESEGVERTEX);
18311 for (i = 0; i < 3; i++) {
18312 steinpt[i] = 0.5 * (pa[i] + pb[i]);
18314 point2tetorg(pa, searchtet);
18315 ivf.iloc = (int) OUTSIDE;
18317 if (!insertpoint_cdt(steinpt, &searchtet, &splitsh, &splitseg, &ivf,
18318 cavpoints, cavfaces, cavshells, newtets,
18319 crosstets, misfaces)) {
18320 terminatetetgen(
this, 2);
18322 if (useinsertradius) {
18323 save_segmentpoint_insradius(steinpt, ivf.parentpt, ivf.smlen);
18326 if (steinerleft > 0) steinerleft--;
18328 terminatetetgen(
this, 2);
18331 if (useinsertradius) {
18332 save_facetpoint_insradius(steinpt, ivf.parentpt, ivf.smlen);
18335 if (steinerleft > 0) steinerleft--;
18338 while (subsegstack->objects > 0l) {
18340 subsegstack->objects--;
18341 paryseg = (face *) fastlookup(subsegstack, subsegstack->objects);
18342 splitseg = *paryseg;
18345 sstpivot1(splitseg, searchtet);
18346 if (searchtet.tet != NULL)
continue;
18349 dir = scoutsegment(sorg(splitseg), sdest(splitseg), &splitseg, &searchtet,
18351 if (dir == SHAREEDGE) {
18354 sstbond1(splitseg, searchtet);
18356 spintet = searchtet;
18358 tssbond1(spintet, splitseg);
18359 fnextself(spintet);
18360 }
while (spintet.tet != searchtet.tet);
18362 if ((dir == ACROSSFACE) || (dir == ACROSSEDGE)) {
18364 makepoint(&steinpt, FREESEGVERTEX);
18365 getsteinerptonsegment(&splitseg, refpt, steinpt);
18366 ivf.iloc = (int) OUTSIDE;
18368 if (!insertpoint_cdt(steinpt, &searchtet, &splitsh, &splitseg, &ivf,
18369 cavpoints, cavfaces, cavshells, newtets,
18370 crosstets, misfaces)) {
18371 terminatetetgen(
this, 2);
18373 if (useinsertradius) {
18374 save_segmentpoint_insradius(steinpt, ivf.parentpt, ivf.smlen);
18377 if (steinerleft > 0) steinerleft--;
18379 terminatetetgen(
this, 2);
18384 if (b->verbose > 2) {
18385 printf(
" Added %ld Steiner points.\n", points->items - baknum);
18397 void tetgenmesh::constrainedfacets()
18399 arraypool *tg_crosstets, *tg_topnewtets, *tg_botnewtets;
18400 arraypool *tg_topfaces, *tg_botfaces, *tg_midfaces;
18401 arraypool *tg_topshells, *tg_botshells, *tg_facfaces;
18402 arraypool *tg_toppoints, *tg_botpoints;
18403 arraypool *tg_missingshs, *tg_missingshbds, *tg_missingshverts;
18404 triface searchtet, neightet, crossedge;
18405 face searchsh, *parysh, *parysh1;
18408 enum interresult dir;
18415 tg_crosstets =
new arraypool(
sizeof(triface), 10);
18416 tg_topnewtets =
new arraypool(
sizeof(triface), 10);
18417 tg_botnewtets =
new arraypool(
sizeof(triface), 10);
18418 tg_topfaces =
new arraypool(
sizeof(triface), 10);
18419 tg_botfaces =
new arraypool(
sizeof(triface), 10);
18420 tg_midfaces =
new arraypool(
sizeof(triface), 10);
18421 tg_toppoints =
new arraypool(
sizeof(point), 8);
18422 tg_botpoints =
new arraypool(
sizeof(point), 8);
18423 tg_facfaces =
new arraypool(
sizeof(face), 10);
18424 tg_topshells =
new arraypool(
sizeof(face), 10);
18425 tg_botshells =
new arraypool(
sizeof(face), 10);
18426 tg_missingshs =
new arraypool(
sizeof(face), 10);
18427 tg_missingshbds =
new arraypool(
sizeof(face), 10);
18428 tg_missingshverts =
new arraypool(
sizeof(point), 8);
18430 encseglist =
new arraypool(
sizeof(face), 4);
18434 while (subfacstack->objects > 0l) {
18436 subfacstack->objects--;
18437 parysh = (face *) fastlookup(subfacstack, subfacstack->objects);
18438 searchsh = *parysh;
18440 if (searchsh.sh[3] == NULL)
continue;
18441 if (isshtet(searchsh))
continue;
18444 smarktest(searchsh);
18445 tg_facfaces->newindex((
void **) &parysh);
18446 *parysh = searchsh;
18447 for (i = 0; i < tg_facfaces->objects; i++) {
18448 parysh = (face *) fastlookup(tg_facfaces, i);
18449 for (j = 0; j < 3; j++) {
18450 if (!isshsubseg(*parysh)) {
18451 spivot(*parysh, searchsh);
18452 if (!smarktested(searchsh)) {
18453 if (!isshtet(searchsh)) {
18454 smarktest(searchsh);
18455 tg_facfaces->newindex((
void **) &parysh1);
18456 *parysh1 = searchsh;
18460 senextself(*parysh);
18464 for (i = 0; i < tg_facfaces->objects; i++) {
18465 parysh = (face *) fastlookup(tg_facfaces, i);
18466 sunmarktest(*parysh);
18469 if (b->verbose > 1) {
18470 printf(
" Recovering facet #%d: %ld subfaces.\n", facetcount + 1,
18471 tg_facfaces->objects);
18475 while (tg_facfaces->objects > 0l) {
18477 tg_facfaces->objects--;
18478 parysh = (face *) fastlookup(tg_facfaces, tg_facfaces->objects);
18479 searchsh = *parysh;
18481 if (searchsh.sh[3] == NULL)
continue;
18482 if (isshtet(searchsh))
continue;
18484 searchtet.tet = NULL;
18485 if (scoutsubface(&searchsh, &searchtet, 1))
continue;
18489 formregion(&searchsh, tg_missingshs, tg_missingshbds, tg_missingshverts);
18491 int searchflag = scoutcrossedge(searchtet, tg_missingshbds, tg_missingshs);
18492 if (searchflag > 0) {
18494 crossedge = searchtet;
18496 success = formcavity(&searchtet, tg_missingshs, tg_crosstets,
18497 tg_topfaces, tg_botfaces, tg_toppoints,
18500 if (!b->flipinsert) {
18502 delaunizecavity(tg_toppoints, tg_topfaces, tg_topshells,
18503 tg_topnewtets, tg_crosstets, tg_midfaces);
18505 delaunizecavity(tg_botpoints, tg_botfaces, tg_botshells,
18506 tg_botnewtets, tg_crosstets, tg_midfaces);
18508 success = fillcavity(tg_topshells, tg_botshells, tg_midfaces,
18509 tg_missingshs, tg_topnewtets, tg_botnewtets,
18513 carvecavity(tg_crosstets, tg_topnewtets, tg_botnewtets);
18515 restorecavity(tg_crosstets, tg_topnewtets, tg_botnewtets,
18520 flipinsertfacet(tg_crosstets, tg_toppoints, tg_botpoints,
18521 tg_missingshverts);
18523 for (i = 0; i < tg_missingshs->objects; i++) {
18524 parysh = (face *) fastlookup(tg_missingshs, i);
18525 tg_facfaces->newindex((
void **) &parysh1);
18526 *parysh1 = *parysh;
18530 tg_crosstets->restart();
18531 tg_topfaces->restart();
18532 tg_botfaces->restart();
18533 tg_toppoints->restart();
18534 tg_botpoints->restart();
18539 for (i = 0; i < caveencshlist->objects; i++) {
18540 parysh = (face *) fastlookup(caveencshlist, i);
18541 if (!scoutsubface(parysh, &searchtet, 1)) {
18544 tg_facfaces->newindex((
void **) &parysh1);
18545 *parysh1 = *parysh;
18548 caveencshlist->restart();
18550 for (i = 0; i < caveencseglist->objects; i++) {
18551 paryseg = (face *) fastlookup(caveencseglist, i);
18552 dir = scoutsegment(sorg(*paryseg), sdest(*paryseg), paryseg,
18553 &searchtet, NULL, NULL);
18554 if (dir != SHAREEDGE) {
18555 terminatetetgen(
this, 2);
18559 sstbond1(*paryseg, searchtet);
18561 neightet = searchtet;
18563 tssbond1(neightet, *paryseg);
18564 fnextself(neightet);
18565 }
while (neightet.tet != searchtet.tet);
18567 caveencseglist->restart();
18571 terminatetetgen(
this, 2);
18575 for (i = 0; i < tg_missingshs->objects; i++) {
18576 parysh = (face *) fastlookup(tg_missingshs, i);
18577 tg_facfaces->newindex((
void **) &parysh1);
18578 *parysh1 = *parysh;
18580 if (searchflag != -1) {
18584 restorecavity(tg_crosstets, tg_topnewtets, tg_botnewtets,
18587 recentsh = searchsh;
18593 for (i = 0; i < tg_missingshverts->objects; i++) {
18594 parypt = (point *) fastlookup(tg_missingshverts, i);
18595 punmarktest(*parypt);
18597 tg_missingshverts->restart();
18598 tg_missingshbds->restart();
18599 tg_missingshs->restart();
18603 refineregion(recentsh, tg_toppoints, tg_topfaces, tg_topshells,
18604 tg_topnewtets, tg_crosstets, tg_midfaces);
18611 totalworkmemory += (tg_crosstets->totalmemory + tg_topnewtets->totalmemory +
18612 tg_botnewtets->totalmemory + tg_topfaces->totalmemory +
18613 tg_botfaces->totalmemory + tg_midfaces->totalmemory +
18614 tg_toppoints->totalmemory + tg_botpoints->totalmemory +
18615 tg_facfaces->totalmemory + tg_topshells->totalmemory +
18616 tg_botshells->totalmemory + tg_missingshs->totalmemory +
18617 tg_missingshbds->totalmemory +
18618 tg_missingshverts->totalmemory +
18619 encseglist->totalmemory);
18622 delete tg_crosstets;
18623 delete tg_topnewtets;
18624 delete tg_botnewtets;
18625 delete tg_topfaces;
18626 delete tg_botfaces;
18627 delete tg_midfaces;
18628 delete tg_toppoints;
18629 delete tg_botpoints;
18630 delete tg_facfaces;
18631 delete tg_topshells;
18632 delete tg_botshells;
18633 delete tg_missingshs;
18634 delete tg_missingshbds;
18635 delete tg_missingshverts;
18646 void tetgenmesh::constraineddelaunay(clock_t& tv)
18648 face searchsh, *parysh;
18649 face searchseg, *paryseg;
18653 long bakfillregioncount;
18654 long bakcavitycount, bakcavityexpcount;
18655 long bakseg_ref_count;
18658 printf(
"Constrained Delaunay...\n");
18661 makesegmentendpointsmap();
18662 makefacetverticesmap();
18665 printf(
" Delaunizing segments.\n");
18668 checksubsegflag = 1;
18671 subsegs->traversalinit();
18672 for (i = 0; i < subsegs->items; i++) {
18673 s = randomnation(i + 1);
18675 subsegstack->newindex((
void **) &paryseg);
18676 *paryseg = * (face *) fastlookup(subsegstack, s);
18678 searchseg.sh = shellfacetraverse(subsegs);
18680 paryseg = (face *) fastlookup(subsegstack, s);
18681 *paryseg = searchseg;
18685 delaunizesegments();
18688 printf(
" Inserted %ld Steiner points.\n", st_segref_count);
18694 printf(
" Constraining facets.\n");
18698 checksubfaceflag = 1;
18700 bakfillregioncount = fillregioncount;
18701 bakcavitycount = cavitycount;
18702 bakcavityexpcount = cavityexpcount;
18703 bakseg_ref_count = st_segref_count;
18706 subfaces->traversalinit();
18707 for (i = 0; i < subfaces->items; i++) {
18708 s = randomnation(i + 1);
18710 subfacstack->newindex((
void **) &parysh);
18711 *parysh = * (face *) fastlookup(subfacstack, s);
18713 searchsh.sh = shellfacetraverse(subfaces);
18714 parysh = (face *) fastlookup(subfacstack, s);
18715 *parysh = searchsh;
18719 constrainedfacets();
18722 if (fillregioncount > bakfillregioncount) {
18723 printf(
" Remeshed %ld regions.\n", fillregioncount-bakfillregioncount);
18725 if (cavitycount > bakcavitycount) {
18726 printf(
" Remeshed %ld cavities", cavitycount - bakcavitycount);
18727 if (cavityexpcount - bakcavityexpcount) {
18728 printf(
" (%ld enlarged)", cavityexpcount - bakcavityexpcount);
18732 if (st_segref_count + st_facref_count - bakseg_ref_count > 0) {
18733 printf(
" Inserted %ld (%ld, %ld) refine points.\n",
18734 st_segref_count + st_facref_count - bakseg_ref_count,
18735 st_segref_count - bakseg_ref_count, st_facref_count);
18761 int tetgenmesh::checkflipeligibility(
int fliptype, point pa, point pb,
18762 point pc, point pd, point pe,
18763 int level,
int edgepivot,
18764 flipconstraints* fc)
18767 enum interresult dir;
18768 int types[2], poss[4];
18773 if (fc->seg[0] != NULL) {
18775 if (fliptype == 1) {
18780 for (i = 0; i < 3 && !rejflag; i++) {
18781 if (tmppts[i] != dummypoint) {
18783 intflag = tri_edge_test(pe, pd, tmppts[i], fc->seg[0], fc->seg[1],
18784 NULL, 1, types, poss);
18785 if (intflag == 2) {
18787 dir = (
enum interresult) types[0];
18788 if (dir == ACROSSFACE) {
18791 }
else if (dir == ACROSSEDGE) {
18792 if (poss[0] == 0) {
18798 }
else if (intflag == 4) {
18800 dir = (
enum interresult) types[0];
18801 if (dir == ACROSSEDGE) {
18802 if (poss[0] == 0) {
18811 }
else if (fliptype == 2) {
18813 if (pc != dummypoint) {
18815 intflag = tri_edge_test(pa, pb, pc, fc->seg[0], fc->seg[1], NULL,
18817 if (intflag == 2) {
18819 dir = (
enum interresult) types[0];
18820 if (dir == ACROSSFACE) {
18824 }
else if (intflag == 4) {
18826 dir = (
enum interresult) types[0];
18827 if (dir == ACROSSEDGE) {
18836 if ((fc->fac[0] != NULL) && !rejflag) {
18838 if (fliptype == 1) {
18841 intflag = tri_edge_test(fc->fac[0], fc->fac[1], fc->fac[2], pe, pd,
18842 NULL, 1, types, poss);
18843 if (intflag == 2) {
18845 dir = (
enum interresult) types[0];
18846 if (dir == ACROSSFACE) {
18848 }
else if (dir == ACROSSEDGE) {
18851 }
else if (intflag == 4) {
18854 for (i = 0; i < 2 && !rejflag; i++) {
18855 dir = (
enum interresult) types[i];
18856 if (dir == ACROSSFACE) {
18858 }
else if (dir == ACROSSEDGE) {
18866 if ((fc->remvert != NULL) && !rejflag) {
18869 if (fliptype == 1) {
18871 if ((pd == fc->remvert) || (pe == fc->remvert)) {
18877 if (fc->remove_large_angle && !rejflag) {
18879 REAL cosmaxd = 0, diff;
18880 if (fliptype == 1) {
18885 if ((pc != dummypoint) && (pe != dummypoint) && (pd != dummypoint)) {
18887 tetalldihedral(pe, pd, pb, pc, NULL, &cosmaxd, NULL);
18888 diff = cosmaxd - fc->cosdihed_in;
18889 if (fabs(diff/fc->cosdihed_in) < b->epsilon) diff = 0.0;
18894 if (cosmaxd < fc->cosdihed_out) {
18895 fc->cosdihed_out = cosmaxd;
18898 tetalldihedral(pe, pd, pc, pa, NULL, &cosmaxd, NULL);
18899 diff = cosmaxd - fc->cosdihed_in;
18900 if (fabs(diff/fc->cosdihed_in) < b->epsilon) diff = 0.0;
18905 if (cosmaxd < fc->cosdihed_out) {
18906 fc->cosdihed_out = cosmaxd;
18911 }
else if (fliptype == 2) {
18916 if ((pa != dummypoint) && (pb != dummypoint) && (pc != dummypoint)) {
18918 tetalldihedral(pa, pb, pc, pd, NULL, &cosmaxd, NULL);
18919 diff = cosmaxd - fc->cosdihed_in;
18920 if (fabs(diff/fc->cosdihed_in) < b->epsilon) diff = 0.0;
18925 if (cosmaxd < fc->cosdihed_out) {
18926 fc->cosdihed_out = cosmaxd;
18929 tetalldihedral(pb, pa, pc, pe, NULL, &cosmaxd, NULL);
18930 diff = cosmaxd - fc->cosdihed_in;
18931 if (fabs(diff/fc->cosdihed_in) < b->epsilon) diff = 0.0;
18936 if (cosmaxd < fc->cosdihed_out) {
18937 fc->cosdihed_out = cosmaxd;
18943 if (edgepivot == 1) {
18945 if ((pa != dummypoint) && (pb != dummypoint) && (pc != dummypoint)) {
18947 tetalldihedral(pb, pa, pc, pe, NULL, &cosmaxd, NULL);
18948 diff = cosmaxd - fc->cosdihed_in;
18949 if (fabs(diff/fc->cosdihed_in) < b->epsilon) diff = 0.0;
18954 if (cosmaxd < fc->cosdihed_out) {
18955 fc->cosdihed_out = cosmaxd;
18961 if ((pa != dummypoint) && (pb != dummypoint) && (pc != dummypoint)) {
18963 tetalldihedral(pa, pb, pc, pd, NULL, &cosmaxd, NULL);
18964 diff = cosmaxd - fc->cosdihed_in;
18965 if (fabs(diff/fc->cosdihed_in) < b->epsilon) diff = 0.0;
18970 if (cosmaxd < fc->cosdihed_out) {
18971 fc->cosdihed_out = cosmaxd;
18996 int tetgenmesh::removeedgebyflips(triface *flipedge, flipconstraints* fc)
18998 triface *abtets, spintet;
19003 if (checksubsegflag) {
19005 if (issubseg(*flipedge)) {
19006 if (fc->collectencsegflag) {
19007 face checkseg, *paryseg;
19008 tsspivot1(*flipedge, checkseg);
19009 if (!sinfected(checkseg)) {
19012 caveencseglist->newindex((
void **) &paryseg);
19013 *paryseg = checkseg;
19022 spintet = *flipedge;
19025 fnextself(spintet);
19026 if (spintet.tet == flipedge->tet)
break;
19030 terminatetetgen(
this, 2);
19033 if ((b->flipstarsize > 0) && (n > b->flipstarsize)) {
19039 abtets =
new triface[n];
19041 spintet = *flipedge;
19044 abtets[i] = spintet;
19045 setelemcounter(abtets[i], 1);
19047 fnextself(spintet);
19048 if (spintet.tet == flipedge->tet)
break;
19053 nn = flipnm(abtets, n, 0, 0, fc);
19058 for (i = 0; i < nn; i++) {
19059 setelemcounter(abtets[i], 0);
19062 *flipedge = abtets[0];
19067 int bakunflip = fc->unflip;
19069 flipnm_post(abtets, n, nn, 0, fc);
19070 fc->unflip = bakunflip;
19089 int tetgenmesh::removefacebyflips(triface *flipface, flipconstraints* fc)
19091 triface fliptets[3], flipedge;
19092 point pa, pb, pc, pd, pe;
19096 fliptets[0] = *flipface;
19097 fsym(*flipface, fliptets[1]);
19098 pa = org(fliptets[0]);
19099 pb = dest(fliptets[0]);
19100 pc = apex(fliptets[0]);
19101 pd = oppo(fliptets[0]);
19102 pe = oppo(fliptets[1]);
19104 ori = orient3d(pa, pb, pd, pe);
19106 ori = orient3d(pb, pc, pd, pe);
19108 ori = orient3d(pc, pa, pd, pe);
19113 eprev(*flipface, flipedge);
19116 enext(*flipface, flipedge);
19119 flipedge = *flipface;
19124 flip23(fliptets, 0, fc);
19128 if (removeedgebyflips(&flipedge, fc) == 2) {
19157 int tetgenmesh::recoveredgebyflips(point startpt, point endpt, face *sedge,
19158 triface* searchtet,
int fullsearch)
19160 flipconstraints fc;
19161 enum interresult dir;
19163 fc.seg[0] = startpt;
19165 fc.checkflipeligibility = 1;
19171 point2tetorg(startpt, *searchtet);
19172 dir = finddirection(searchtet, endpt);
19173 if (dir == ACROSSVERT) {
19174 if (dest(*searchtet) == endpt) {
19178 return report_selfint_edge(startpt, endpt, sedge, searchtet, dir);
19188 enextesymself(*searchtet);
19189 if (dir == ACROSSFACE) {
19190 if (checksubfaceflag) {
19191 if (issubface(*searchtet)) {
19193 return report_selfint_edge(startpt, endpt, sedge, searchtet, dir);
19200 if (removefacebyflips(searchtet, &fc)) {
19203 }
else if (dir == ACROSSEDGE) {
19204 if (checksubsegflag) {
19205 if (issubseg(*searchtet)) {
19207 return report_selfint_edge(startpt, endpt, sedge, searchtet, dir);
19214 if (removeedgebyflips(searchtet, &fc) == 2) {
19223 triface neightet, spintet;
19224 point pa, pb, pc, pd;
19226 enum interresult dir1;
19227 int types[2], poss[4], pos = 0;
19234 point2tetorg(startpt, *searchtet);
19235 dir = finddirection(searchtet, endpt);
19238 enextesymself(*searchtet);
19244 fsymself(*searchtet);
19245 if (dir == ACROSSFACE) {
19246 neightet = *searchtet;
19247 j = (neightet.ver & 3);
19248 for (i = j + 1; i < j + 4; i++) {
19249 neightet.ver = (i % 4);
19250 pa = org(neightet);
19251 pb = dest(neightet);
19252 pc = apex(neightet);
19253 pd = oppo(neightet);
19254 if (tri_edge_test(pa,pb,pc,startpt,endpt, pd, 1, types, poss)) {
19255 dir = (
enum interresult) types[0];
19264 if (dir == DISJOINT) {
19265 terminatetetgen(
this, 2);
19267 }
else if (dir == ACROSSEDGE) {
19270 for (i = 0; i < 2; i++) {
19272 enextesym(*searchtet, neightet);
19274 eprevesym(*searchtet, neightet);
19276 pa = org(neightet);
19277 pb = dest(neightet);
19278 pc = apex(neightet);
19279 pd = oppo(neightet);
19280 if (tri_edge_test(pa,pb,pc,startpt,endpt,pd,1, types, poss)) {
19281 dir = (
enum interresult) types[0];
19289 if (dir != DISJOINT) {
19294 fnextself(*searchtet);
19297 terminatetetgen(
this, 2);
19301 for (i = 0; i < pos; i++) {
19302 enextself(neightet);
19305 if (dir == SHAREVERT) {
19307 pd = org(neightet);
19312 terminatetetgen(
this, 2);
19317 *searchtet = neightet;
19320 bakface.forg = org(*searchtet);
19321 bakface.fdest = dest(*searchtet);
19322 bakface.fapex = apex(*searchtet);
19323 bakface.foppo = oppo(*searchtet);
19326 if (dir == ACROSSFACE) {
19327 if (checksubfaceflag) {
19328 if (issubface(*searchtet)) {
19330 return report_selfint_edge(startpt,endpt,sedge,searchtet,dir);
19336 if (removefacebyflips(searchtet, &fc)) {
19340 }
else if (dir == ACROSSEDGE) {
19341 if (checksubsegflag) {
19342 if (issubseg(*searchtet)) {
19344 return report_selfint_edge(startpt,endpt,sedge,searchtet,dir);
19350 if (removeedgebyflips(searchtet, &fc) == 2) {
19354 }
else if (dir == ACROSSVERT) {
19357 terminatetetgen(
this, 2);
19362 terminatetetgen(
this, 2);
19366 if ((searchtet->tet == NULL) ||
19367 (org(*searchtet) != bakface.forg) ||
19368 (dest(*searchtet) != bakface.fdest) ||
19369 (apex(*searchtet) != bakface.fapex) ||
19370 (oppo(*searchtet) != bakface.foppo)) {
19372 point2tetorg(bakface.forg, *searchtet);
19373 dir1 = finddirection(searchtet, bakface.fdest);
19374 if (dir1 == ACROSSVERT) {
19375 if (dest(*searchtet) == bakface.fdest) {
19376 spintet = *searchtet;
19378 if (apex(spintet) == bakface.fapex) {
19380 *searchtet = spintet;
19383 fnextself(spintet);
19384 if (spintet.tet == searchtet->tet) {
19385 searchtet->tet = NULL;
19389 if (searchtet->tet != NULL) {
19390 if (oppo(*searchtet) != bakface.foppo) {
19391 fsymself(*searchtet);
19392 if (oppo(*searchtet) != bakface.foppo) {
19394 searchtet->tet = NULL;
19400 searchtet->tet = NULL;
19403 searchtet->tet = NULL;
19405 if (searchtet->tet == NULL) {
19441 int tetgenmesh::add_steinerpt_in_schoenhardtpoly(triface *abtets,
int n,
19444 triface worktet, *parytet;
19445 triface faketet1, faketet2;
19446 point pc, pd, steinerpt;
19447 insertvertexflags ivf;
19449 REAL vcd[3], sampt[3], smtpt[3];
19450 REAL maxminvol = 0.0, minvol = 0.0, ori;
19451 int success, maxidx = 0;
19455 pc = apex(abtets[0]);
19456 pd = oppo(abtets[n-1]);
19463 for (i = 0; i < n; i++) {
19464 edestoppo(abtets[i], worktet);
19465 cavetetlist->newindex((
void **) &parytet);
19466 *parytet = worktet;
19467 eorgoppo(abtets[i], worktet);
19468 cavetetlist->newindex((
void **) &parytet);
19469 *parytet = worktet;
19476 for (i = 0; i < 3; i++) vcd[i] = pd[i] - pc[i];
19479 for (it = 1; it < N; it++) {
19480 for (i = 0; i < 3; i++) {
19481 sampt[i] = pc[i] + (stepi * (double) it) * vcd[i];
19483 for (i = 0; i < cavetetlist->objects; i++) {
19484 parytet = (triface *) fastlookup(cavetetlist, i);
19485 ori = orient3d(dest(*parytet), org(*parytet), apex(*parytet), sampt);
19489 if (minvol > ori) minvol = ori;
19493 maxminvol = minvol;
19496 if (maxminvol < minvol) {
19497 maxminvol = minvol;
19503 if (maxminvol <= 0) {
19504 cavetetlist->restart();
19508 for (i = 0; i < 3; i++) {
19509 smtpt[i] = pc[i] + (stepi * (double) maxidx) * vcd[i];
19514 maketetrahedron(&faketet1);
19515 setvertices(faketet1, pd, pc, org(abtets[0]), dummypoint);
19516 cavetetlist->newindex((
void **) &parytet);
19517 *parytet = faketet1;
19518 maketetrahedron(&faketet2);
19519 setvertices(faketet2, pc, pd, dest(abtets[0]), dummypoint);
19520 cavetetlist->newindex((
void **) &parytet);
19521 *parytet = faketet2;
19524 opm.max_min_volume = 1;
19525 opm.numofsearchdirs = 20;
19526 opm.searchstep = 0.001;
19531 success = smoothpoint(smtpt, cavetetlist, 1, &opm);
19534 while (opm.smthiter == 100) {
19537 opm.searchstep *= 10.0;
19539 opm.initval = opm.imprval;
19541 smoothpoint(smtpt, cavetetlist, 1, &opm);
19546 tetrahedrondealloc(faketet1.tet);
19547 tetrahedrondealloc(faketet2.tet);
19549 cavetetlist->restart();
19557 makepoint(&steinerpt, FREEVOLVERTEX);
19558 for (i = 0; i < 3; i++) steinerpt[i] = smtpt[i];
19561 for (i = 0; i < n; i++) {
19563 caveoldtetlist->newindex((
void **) &parytet);
19564 *parytet = abtets[i];
19566 worktet = abtets[0];
19567 ivf.iloc = (int) INSTAR;
19568 ivf.chkencflag = chkencflag;
19569 ivf.assignmeshsize = b->metric;
19570 if (ivf.assignmeshsize) {
19572 locate(steinerpt, &(abtets[0]));
19573 worktet = abtets[0];
19578 if (insertpoint(steinerpt, &worktet, NULL, NULL, &ivf)) {
19581 if (steinerleft > 0) steinerleft--;
19585 pointdealloc(steinerpt);
19596 int tetgenmesh::add_steinerpt_in_segment(face* misseg,
int searchlevel)
19599 face *paryseg, candseg;
19600 point startpt, endpt, pc, pd;
19601 flipconstraints fc;
19602 enum interresult dir;
19603 REAL P[3], Q[3], tp, tq;
19604 REAL len, smlen = 0, split = 0, split_q = 0;
19608 startpt = sorg(*misseg);
19609 endpt = sdest(*misseg);
19611 fc.seg[0] = startpt;
19613 fc.checkflipeligibility = 1;
19614 fc.collectencsegflag = 1;
19616 point2tetorg(startpt, searchtet);
19617 dir = finddirection(&searchtet, endpt);
19619 enextesymself(searchtet);
19621 int bak_fliplinklevel = b->fliplinklevel;
19622 b->fliplinklevel = searchlevel;
19624 if (dir == ACROSSFACE) {
19626 success = removefacebyflips(&searchtet, &fc);
19627 }
else if (dir == ACROSSEDGE) {
19629 success = removeedgebyflips(&searchtet, &fc);
19633 for (i = 0; i < caveencseglist->objects; i++) {
19634 paryseg = (face *) fastlookup(caveencseglist, i);
19635 suninfect(*paryseg);
19637 pc = sorg(*paryseg);
19638 pd = sdest(*paryseg);
19640 if (linelineint(startpt, endpt, pc, pd, P, Q, &tp, &tq)) {
19643 if ((tp > 0) && (tq < 1)) {
19645 if (tp < (b->epsilon * 1e+3)) tp = 0.0;
19647 if ((1.0 - tp) < (b->epsilon * 1e+3)) tp = 1.0;
19650 if ((tp <= 0) || (tp >= 1))
continue;
19651 if ((tq > 0) && (tq < 1)) {
19653 if (tq < (b->epsilon * 1e+3)) tq = 0.0;
19655 if ((1.0 - tq) < (b->epsilon * 1e+3)) tq = 1.0;
19658 if ((tq <= 0) || (tq >= 1))
continue;
19660 len = distance(P, Q);
19665 candseg = *paryseg;
19671 candseg = *paryseg;
19677 caveencseglist->restart();
19678 b->fliplinklevel = bak_fliplinklevel;
19687 point steinerpt, *parypt;
19688 insertvertexflags ivf;
19690 if (b->addsteiner_algo == 1) {
19692 makepoint(&steinerpt, FREESEGVERTEX);
19693 for (i = 0; i < 3; i++) {
19694 steinerpt[i] = startpt[i] + split * (endpt[i] - startpt[i]);
19697 for (i = 0; i < 3; i++) {
19698 P[i] = startpt[i] + split * (endpt[i] - startpt[i]);
19700 pc = sorg(candseg);
19701 pd = sdest(candseg);
19702 for (i = 0; i < 3; i++) {
19703 Q[i] = pc[i] + split_q * (pd[i] - pc[i]);
19705 makepoint(&steinerpt, FREEVOLVERTEX);
19706 for (i = 0; i < 3; i++) {
19707 steinerpt[i] = 0.5 * (P[i] + Q[i]);
19713 point2tetorg(startpt, searchtet);
19715 point2tetorg(endpt, searchtet);
19717 if (b->addsteiner_algo == 1) {
19718 splitseg = *misseg;
19719 spivot(*misseg, splitsh);
19722 splitseg.sh = NULL;
19724 ivf.iloc = (int) OUTSIDE;
19728 ivf.chkencflag = 0;
19729 ivf.sloc = (int) ONEDGE;
19731 ivf.splitbdflag = 0;
19733 ivf.respectbdflag = 1;
19734 ivf.assignmeshsize = b->metric;
19736 if (!insertpoint(steinerpt, &searchtet, &splitsh, &splitseg, &ivf)) {
19737 pointdealloc(steinerpt);
19741 if (b->addsteiner_algo == 1) {
19744 subvertstack->newindex((
void **) &parypt);
19745 *parypt = steinerpt;
19749 subsegstack->newindex((
void **) &paryseg);
19750 *paryseg = *misseg;
19753 if (steinerleft > 0) steinerleft--;
19764 int tetgenmesh::addsteiner4recoversegment(face* misseg,
int splitsegflag)
19766 triface *abtets, searchtet, spintet;
19769 point startpt, endpt;
19770 point pa, pb, pd, steinerpt, *parypt;
19771 enum interresult dir;
19772 insertvertexflags ivf;
19773 int types[2], poss[4];
19774 int n, endi, success;
19778 startpt = sorg(*misseg);
19779 if (pointtype(startpt) == FREESEGVERTEX) {
19780 sesymself(*misseg);
19781 startpt = sorg(*misseg);
19783 endpt = sdest(*misseg);
19786 point2tetorg(startpt, searchtet);
19787 dir = finddirection(&searchtet, endpt);
19788 enextself(searchtet);
19790 if (dir == ACROSSFACE) {
19793 esymself(searchtet);
19794 fsym(searchtet, spintet);
19795 pd = oppo(spintet);
19796 for (i = 0; i < 3; i++) {
19798 pb = dest(spintet);
19799 if (tri_edge_test(pa, pb, pd, startpt, endpt, NULL, 1, types, poss)) {
19802 enextself(spintet);
19803 eprevself(searchtet);
19805 esymself(searchtet);
19808 spintet = searchtet;
19812 if (apex(spintet) == endpt) {
19816 fnextself(spintet);
19817 if (spintet.tet == searchtet.tet)
break;
19823 abtets =
new triface[n];
19824 spintet = searchtet;
19825 for (i = 0; i < n; i++) {
19826 abtets[i] = spintet;
19827 fnextself(spintet);
19832 if (dir == ACROSSFACE) {
19834 if (add_steinerpt_in_schoenhardtpoly(abtets, endi, 0)) {
19837 }
else if (dir == ACROSSEDGE) {
19839 if (issubseg(searchtet)) {
19840 terminatetetgen(
this, 2);
19850 if (add_steinerpt_in_schoenhardtpoly(abtets, endi, 0)) {
19854 if ((n - endi) > 2) {
19856 if (add_steinerpt_in_schoenhardtpoly(&(abtets[endi]), n - endi, 0)) {
19865 terminatetetgen(
this, 2);
19868 terminatetetgen(
this, 2);
19875 subsegstack->newindex((
void **) &paryseg);
19876 *paryseg = *misseg;
19881 if (!splitsegflag) {
19885 if (b->verbose > 2) {
19886 printf(
" Splitting segment (%d, %d)\n", pointmark(startpt),
19891 if (b->addsteiner_algo > 0) {
19892 if (add_steinerpt_in_segment(misseg, 3)) {
19895 sesymself(*misseg);
19896 if (add_steinerpt_in_segment(misseg, 3)) {
19899 sesymself(*misseg);
19905 if (steinerpt == NULL) {
19907 makepoint(&steinerpt, FREESEGVERTEX);
19908 for (i = 0; i < 3; i++) {
19909 steinerpt[i] = 0.5 * (startpt[i] + endpt[i]);
19913 spivot(*misseg, splitsh);
19914 ivf.iloc = (int) OUTSIDE;
19918 ivf.chkencflag = 0;
19919 ivf.sloc = (int) ONEDGE;
19921 ivf.splitbdflag = 0;
19923 ivf.respectbdflag = 1;
19924 ivf.assignmeshsize = b->metric;
19925 if (!insertpoint(steinerpt, &searchtet, &splitsh, misseg, &ivf)) {
19926 terminatetetgen(
this, 2);
19932 subvertstack->newindex((
void **) &parypt);
19933 *parypt = steinerpt;
19936 if (steinerleft > 0) steinerleft--;
19953 int tetgenmesh::recoversegments(arraypool *misseglist,
int fullsearch,
19956 triface searchtet, spintet;
19957 face sseg, *paryseg;
19958 point startpt, endpt;
19962 long bak_inpoly_count = st_volref_count;
19963 long bak_segref_count = st_segref_count;
19965 if (b->verbose > 1) {
19966 printf(
" Recover segments [%s level = %2d] #: %ld.\n",
19967 (b->fliplinklevel > 0) ?
"fixed" :
"auto",
19968 (b->fliplinklevel > 0) ? b->fliplinklevel : autofliplinklevel,
19969 subsegstack->objects);
19973 while (subsegstack->objects > 0l) {
19975 subsegstack->objects--;
19976 paryseg = (face *) fastlookup(subsegstack, subsegstack->objects);
19980 sstpivot1(sseg, searchtet);
19981 if (searchtet.tet != NULL) {
19985 startpt = sorg(sseg);
19986 endpt = sdest(sseg);
19988 if (b->verbose > 2) {
19989 printf(
" Recover segment (%d, %d).\n", pointmark(startpt),
19995 if (recoveredgebyflips(startpt, endpt, &sseg, &searchtet, 0)) {
19999 if (recoveredgebyflips(endpt, startpt, &sseg, &searchtet, 0)) {
20004 if (!success && fullsearch) {
20005 if (recoveredgebyflips(startpt, endpt, &sseg, &searchtet, fullsearch)) {
20013 sstbond1(sseg, searchtet);
20015 spintet = searchtet;
20017 tssbond1(spintet, sseg);
20018 fnextself(spintet);
20019 }
while (spintet.tet != searchtet.tet);
20021 if (steinerflag > 0) {
20023 if (addsteiner4recoversegment(&sseg, 0)) {
20026 if (!success && (steinerflag > 1)) {
20028 addsteiner4recoversegment(&sseg, 1);
20033 if (misseglist != NULL) {
20035 misseglist->newindex((
void **) &paryseg);
20044 if (b->verbose > 1) {
20046 if (st_volref_count > bak_inpoly_count) {
20047 printf(
" Add %ld Steiner points in volume.\n",
20048 st_volref_count - bak_inpoly_count);
20050 if (st_segref_count > bak_segref_count) {
20051 printf(
" Add %ld Steiner points in segments.\n",
20052 st_segref_count - bak_segref_count);
20077 int tetgenmesh::recoverfacebyflips(point pa, point pb, point pc,
20078 face *searchsh, triface* searchtet)
20080 triface spintet, flipedge;
20082 flipconstraints fc;
20083 int types[2], poss[4], intflag;
20092 fc.checkflipeligibility = 1;
20095 for (i = 0; i < 3 && !success; i++) {
20098 point2tetorg(fc.fac[i], *searchtet);
20099 finddirection(searchtet, fc.fac[(i+1)%3]);
20101 spintet = *searchtet;
20103 if (apex(spintet) == fc.fac[(i+2)%3]) {
20105 *searchtet = spintet;
20107 for (j = i; j > 0; j--) {
20108 eprevself(*searchtet);
20113 fnextself(spintet);
20114 if (spintet.tet == searchtet->tet)
break;
20116 if (success)
break;
20118 flipedge.tet = NULL;
20120 spintet = *searchtet;
20122 pd = apex(spintet);
20123 pe = oppo(spintet);
20124 if ((pd != dummypoint) && (pe != dummypoint)) {
20126 intflag = tri_edge_test(pa, pb, pc, pd, pe, NULL, 1, types, poss);
20130 if (intflag == 2) {
20132 edestoppo(spintet, flipedge);
20133 if (searchsh != NULL) {
20135 if ((types[0] == (
int) ACROSSFACE) ||
20136 (types[0] == (
int) ACROSSEDGE)) {
20138 if (issubseg(flipedge)) {
20139 return report_selfint_face(pa, pb, pc, searchsh, &flipedge,
20140 intflag, types, poss);
20143 triface chkface = flipedge;
20145 if (issubface(chkface))
break;
20147 if (chkface.tet == flipedge.tet)
break;
20149 if (issubface(chkface)) {
20151 return report_selfint_face(pa, pb, pc,searchsh,&chkface,
20152 intflag, types, poss);
20155 }
else if (types[0] == TOUCHFACE) {
20157 point touchpt, *parypt;
20158 if (poss[1] == 0) {
20163 if (pointtype(touchpt) == FREEVOLVERTEX) {
20166 face checksh, *parysh;
20167 int siloc = (int) ONFACE;
20169 setpointtype(touchpt, FREEFACETVERTEX);
20170 sinsertvertex(touchpt, searchsh, NULL, siloc, sbowat, 0);
20174 subvertstack->newindex((
void **) &parypt);
20178 for (i = 0; i < caveshbdlist->objects; i++) {
20180 parysh = (face *) fastlookup(caveshbdlist, i);
20181 spivot(*parysh, checksh);
20183 if (checksh.sh[3] != NULL) {
20184 subfacstack->newindex((
void **) &parysh);
20189 for (i = 0; i < caveshlist->objects; i++) {
20190 parysh = (face *) fastlookup(caveshlist, i);
20191 shellfacedealloc(subfaces, parysh->sh);
20194 caveshlist->restart();
20195 caveshbdlist->restart();
20196 cavesegshlist->restart();
20198 searchsh->sh = NULL;
20202 return report_selfint_face(pa, pb, pc, searchsh, &flipedge,
20203 intflag, types, poss);
20208 return report_selfint_face(pa, pb, pc, searchsh, &flipedge,
20209 intflag, types, poss);
20213 terminatetetgen(
this, 2);
20218 fnextself(spintet);
20219 if (spintet.tet == searchtet->tet) {
20220 terminatetetgen(
this, 2);
20224 if (removeedgebyflips(&flipedge, &fc) == 2) {
20241 int tetgenmesh::recoversubfaces(arraypool *misshlist,
int steinerflag)
20243 triface searchtet, neightet, spintet;
20244 face searchsh, neighsh, neineish, *parysh;
20246 point startpt, endpt, apexpt, *parypt;
20248 insertvertexflags ivf;
20253 if (b->verbose > 1) {
20254 printf(
" Recover subfaces [%s level = %2d] #: %ld.\n",
20255 (b->fliplinklevel > 0) ?
"fixed" :
"auto",
20256 (b->fliplinklevel > 0) ? b->fliplinklevel : autofliplinklevel,
20257 subfacstack->objects);
20261 while (subfacstack->objects > 0l) {
20263 subfacstack->objects--;
20264 parysh = (face *) fastlookup(subfacstack, subfacstack->objects);
20265 searchsh = *parysh;
20267 if (searchsh.sh[3] == NULL)
continue;
20269 stpivot(searchsh, neightet);
20270 if (neightet.tet != NULL)
continue;
20273 if (b->verbose > 2) {
20274 printf(
" Recover subface (%d, %d, %d).\n",pointmark(sorg(searchsh)),
20275 pointmark(sdest(searchsh)), pointmark(sapex(searchsh)));
20279 for (i = 0; i < 3; i++) {
20280 sspivot(searchsh, bdsegs[i]);
20281 if (bdsegs[i].sh != NULL) {
20283 sstpivot1(bdsegs[i], searchtet);
20284 if (searchtet.tet == NULL) {
20285 terminatetetgen(
this, 2);
20291 startpt = sorg(searchsh);
20292 endpt = sdest(searchsh);
20293 point2tetorg(startpt, searchtet);
20294 finddirection(&searchtet, endpt);
20295 if (dest(searchtet) == endpt) {
20299 if (recoveredgebyflips(startpt, endpt, &searchsh, &searchtet, 0)) {
20302 if (recoveredgebyflips(endpt, startpt, &searchsh, &searchtet, 0)) {
20309 makeshellface(subsegs, &(bdsegs[i]));
20310 setshvertices(bdsegs[i], startpt, endpt, NULL);
20311 smarktest2(bdsegs[i]);
20313 ssbond(searchsh, bdsegs[i]);
20314 spivot(searchsh, neighsh);
20315 if (neighsh.sh != NULL) {
20316 ssbond(neighsh, bdsegs[i]);
20319 sstbond1(bdsegs[i], searchtet);
20321 spintet = searchtet;
20323 tssbond1(spintet, bdsegs[i]);
20324 fnextself(spintet);
20325 }
while (spintet.tet != searchtet.tet);
20329 for (j = (i - 1); j >= 0; j--) {
20330 if (smarktest2ed(bdsegs[j])) {
20331 spivot(bdsegs[j], neineish);
20332 ssdissolve(neineish);
20333 spivot(neineish, neighsh);
20334 if (neighsh.sh != NULL) {
20335 ssdissolve(neighsh);
20337 sstpivot1(bdsegs[j], searchtet);
20338 spintet = searchtet;
20340 tssdissolve1(spintet);
20341 fnextself(spintet);
20342 if (spintet.tet == searchtet.tet)
break;
20344 shellfacedealloc(subsegs, bdsegs[j].sh);
20349 if (b->verbose > 2) {
20350 printf(
" Add a Steiner point in subedge (%d, %d).\n",
20351 pointmark(startpt), pointmark(endpt));
20353 makepoint(&steinerpt, FREEFACETVERTEX);
20354 for (j = 0; j < 3; j++) {
20355 steinerpt[j] = 0.5 * (startpt[j] + endpt[j]);
20358 point2tetorg(startpt, searchtet);
20359 ivf.iloc = (int) OUTSIDE;
20363 ivf.chkencflag = 0;
20364 ivf.sloc = (int) ONEDGE;
20366 ivf.splitbdflag = 0;
20368 ivf.respectbdflag = 1;
20369 ivf.assignmeshsize = b->metric;
20370 if (!insertpoint(steinerpt, &searchtet, &searchsh, NULL, &ivf)) {
20371 terminatetetgen(
this, 2);
20375 subvertstack->newindex((
void **) &parypt);
20376 *parypt = steinerpt;
20379 if (steinerleft > 0) steinerleft--;
20384 senextself(searchsh);
20389 startpt = sorg(searchsh);
20390 endpt = sdest(searchsh);
20391 apexpt = sapex(searchsh);
20393 success = recoverfacebyflips(startpt,endpt,apexpt,&searchsh,&searchtet);
20396 for (j = 0; j < 3; j++) {
20397 if (smarktest2ed(bdsegs[j])) {
20398 spivot(bdsegs[j], neineish);
20399 ssdissolve(neineish);
20400 spivot(neineish, neighsh);
20401 if (neighsh.sh != NULL) {
20402 ssdissolve(neighsh);
20404 sstpivot1(bdsegs[j], neightet);
20405 spintet = neightet;
20407 tssdissolve1(spintet);
20408 fnextself(spintet);
20409 if (spintet.tet == neightet.tet)
break;
20411 shellfacedealloc(subsegs, bdsegs[j].sh);
20416 if (searchsh.sh != NULL) {
20418 tsbond(searchtet, searchsh);
20419 fsymself(searchtet);
20420 sesymself(searchsh);
20421 tsbond(searchtet, searchsh);
20426 if (b->verbose > 2) {
20427 printf(
" Add a Steiner point in subface (%d, %d, %d).\n",
20428 pointmark(startpt), pointmark(endpt), pointmark(apexpt));
20430 makepoint(&steinerpt, FREEFACETVERTEX);
20431 for (j = 0; j < 3; j++) {
20432 steinerpt[j] = (startpt[j] + endpt[j] + apexpt[j]) / 3.0;
20435 point2tetorg(startpt, searchtet);
20436 ivf.iloc = (int) OUTSIDE;
20440 ivf.chkencflag = 0;
20441 ivf.sloc = (int) ONFACE;
20443 ivf.splitbdflag = 0;
20445 ivf.respectbdflag = 1;
20446 ivf.assignmeshsize = b->metric;
20447 if (!insertpoint(steinerpt, &searchtet, &searchsh, NULL, &ivf)) {
20448 terminatetetgen(
this, 2);
20452 subvertstack->newindex((
void **) &parypt);
20453 *parypt = steinerpt;
20456 if (steinerleft > 0) steinerleft--;
20464 if (misshlist != NULL) {
20466 misshlist->newindex((
void **) &parysh);
20467 *parysh = searchsh;
20493 int tetgenmesh::getvertexstar(
int fullstar, point searchpt, arraypool* tetlist,
20494 arraypool* vertlist, arraypool* shlist)
20496 triface searchtet, neightet, *parytet;
20497 face checksh, *parysh;
20503 point2tetorg(searchpt, searchtet);
20506 enextesymself(searchtet);
20509 tetlist->newindex((
void **) &parytet);
20510 *parytet = searchtet;
20511 if (vertlist != NULL) {
20513 j = (searchtet.ver & 3);
20514 for (i = 1; i < 4; i++) {
20515 pt = (point) searchtet.tet[4 + ((j + i) % 4)];
20517 vertlist->newindex((
void **) &parypt);
20523 esym(searchtet, neightet);
20524 if (issubface(neightet)) {
20525 if (shlist != NULL) {
20526 tspivot(neightet, checksh);
20527 if (!sinfected(checksh)) {
20529 sinfected(checksh);
20530 shlist->newindex((
void **) &parysh);
20539 fsymself(neightet);
20540 esymself(neightet);
20543 tetlist->newindex((
void **) &parytet);
20544 *parytet = neightet;
20545 if (vertlist != NULL) {
20547 pt = apex(neightet);
20549 vertlist->newindex((
void **) &parypt);
20555 for (i = 0; i < tetlist->objects; i++) {
20556 searchtet = * (triface *) fastlookup(tetlist, i);
20560 for (j = 0; j < 2; j++) {
20562 enextself(searchtet);
20563 esym(searchtet, neightet);
20564 if (issubface(neightet)) {
20565 if (shlist != NULL) {
20566 tspivot(neightet, checksh);
20567 if (!sinfected(checksh)) {
20569 sinfected(checksh);
20570 shlist->newindex((
void **) &parysh);
20579 fsymself(neightet);
20580 if (!infected(neightet)) {
20581 esymself(neightet);
20583 tetlist->newindex((
void **) &parytet);
20584 *parytet = neightet;
20585 if (vertlist != NULL) {
20587 pt = apex(neightet);
20588 if (!pinfected(pt)) {
20590 vertlist->newindex((
void **) &parypt);
20601 for (i = 0; i < tetlist->objects; i++) {
20602 parytet = (triface *) fastlookup(tetlist, i);
20603 uninfect(*parytet);
20606 if (vertlist != NULL) {
20607 for (i = 0; i < vertlist->objects; i++) {
20608 parypt = (point *) fastlookup(vertlist, i);
20609 puninfect(*parypt);
20613 if (shlist != NULL) {
20614 for (i = 0; i < shlist->objects; i++) {
20615 parysh = (face *) fastlookup(shlist, i);
20616 suninfect(*parysh);
20620 return (
int) tetlist->objects;
20635 int tetgenmesh::getedge(point e1, point e2, triface *tedge)
20637 triface searchtet, neightet, *parytet;
20642 if (b->verbose > 2) {
20643 printf(
" Get edge from %d to %d.\n", pointmark(e1), pointmark(e2));
20647 if (!isdeadtet(*tedge)) {
20648 if (org(*tedge) == e1) {
20649 if (dest(*tedge) == e2) {
20652 }
else if (org(*tedge) == e2) {
20653 if (dest(*tedge) == e1) {
20661 point2tetorg(e1, *tedge);
20662 finddirection(tedge, e2);
20663 if (dest(*tedge) == e2) {
20667 point2tetorg(e2, *tedge);
20668 finddirection(tedge, e1);
20669 if (dest(*tedge) == e1) {
20677 point2tetorg(e1, searchtet);
20678 enextesymself(searchtet);
20679 arraypool *tetlist = cavebdrylist;
20682 for (i = 0; i < 3; i++) {
20683 pt = apex(searchtet);
20686 eorgoppo(searchtet, *tedge);
20689 enextself(searchtet);
20693 fnext(searchtet, neightet);
20694 esymself(neightet);
20696 pt = apex(neightet);
20699 eorgoppo(neightet, *tedge);
20705 tetlist->newindex((
void **) &parytet);
20706 *parytet = searchtet;
20708 tetlist->newindex((
void **) &parytet);
20709 *parytet = neightet;
20713 for (i = 0; (i < tetlist->objects) && !done; i++) {
20714 parytet = (triface *) fastlookup(tetlist, i);
20715 searchtet = *parytet;
20716 for (j = 0; (j < 2) && !done; j++) {
20717 enextself(searchtet);
20718 fnext(searchtet, neightet);
20719 if (!infected(neightet)) {
20720 esymself(neightet);
20721 pt = apex(neightet);
20724 eorgoppo(neightet, *tedge);
20728 tetlist->newindex((
void **) &parytet);
20729 *parytet = neightet;
20736 for (i = 0; i < tetlist->objects; i++) {
20737 parytet = (triface *) fastlookup(tetlist, i);
20738 uninfect(*parytet);
20740 tetlist->restart();
20753 int tetgenmesh::reduceedgesatvertex(point startpt, arraypool* endptlist)
20756 point *pendpt, *parypt;
20757 enum interresult dir;
20758 flipconstraints fc;
20764 fc.remvert = startpt;
20765 fc.checkflipeligibility = 1;
20771 for (i = 0; i < endptlist->objects; i++) {
20772 pendpt = (point *) fastlookup(endptlist, i);
20773 if (*pendpt == dummypoint) {
20779 if (getedge(startpt, *pendpt, &searchtet)) {
20786 point2tetorg(startpt, searchtet);
20787 dir = finddirection(&searchtet, *pendpt);
20789 if (dir == ACROSSVERT) {
20790 if (dest(searchtet) == *pendpt) {
20792 if (!issubseg(searchtet)) {
20793 n = removeedgebyflips(&searchtet, &fc);
20806 j = endptlist->objects - 1;
20807 parypt = (point *) fastlookup(endptlist, j);
20809 endptlist->objects--;
20821 return (
int) endptlist->objects;
20840 int tetgenmesh::removevertexbyflips(point steinerpt)
20842 triface *fliptets = NULL, wrktets[4];
20843 triface searchtet, spintet, neightet;
20844 face parentsh, spinsh, checksh;
20845 face leftseg, rightseg, checkseg;
20846 point lpt = NULL, rpt = NULL, apexpt;
20847 flipconstraints fc;
20849 enum locateresult loc;
20850 int valence, removeflag;
20855 vt = pointtype(steinerpt);
20858 if (vt == FREESEGVERTEX) {
20859 sdecode(point2sh(steinerpt), leftseg);
20861 if (sdest(leftseg) == steinerpt) {
20862 senext(leftseg, rightseg);
20863 spivotself(rightseg);
20864 rightseg.shver = 0;
20866 rightseg = leftseg;
20867 senext2(rightseg, leftseg);
20868 spivotself(leftseg);
20871 lpt = sorg(leftseg);
20872 rpt = sdest(rightseg);
20873 if (b->verbose > 2) {
20874 printf(
" Removing Steiner point %d in segment (%d, %d).\n",
20875 pointmark(steinerpt), pointmark(lpt), pointmark(rpt));
20878 }
else if (vt == FREEFACETVERTEX) {
20879 if (b->verbose > 2) {
20880 printf(
" Removing Steiner point %d in facet.\n",
20881 pointmark(steinerpt));
20883 }
else if (vt == FREEVOLVERTEX) {
20884 if (b->verbose > 2) {
20885 printf(
" Removing Steiner point %d in volume.\n",
20886 pointmark(steinerpt));
20888 }
else if (vt == VOLVERTEX) {
20889 if (b->verbose > 2) {
20890 printf(
" Removing a point %d in volume.\n",
20891 pointmark(steinerpt));
20899 getvertexstar(1, steinerpt, cavetetlist, cavetetvertlist, NULL);
20900 cavetetlist->restart();
20901 if (cavetetvertlist->objects > 3l) {
20902 valence = reduceedgesatvertex(steinerpt, cavetetvertlist);
20904 valence = cavetetvertlist->objects;
20906 cavetetvertlist->restart();
20910 if (valence == 4) {
20913 point2tetorg(steinerpt, searchtet);
20914 loc = INTETRAHEDRON;
20916 }
else if (valence == 5) {
20918 if (vt == FREESEGVERTEX) {
20919 sstpivot1(leftseg, searchtet);
20920 if (org(searchtet) != steinerpt) {
20921 esymself(searchtet);
20924 neightet.tet = NULL;
20925 spintet = searchtet;
20928 if (apex(spintet) == rpt) {
20930 neightet = spintet;
20932 fnextself(spintet);
20933 if (spintet.tet == searchtet.tet)
break;
20937 }
else if (i == 4) {
20940 if (apex(neightet) == rpt) {
20944 esym(neightet, searchtet);
20945 enextself(searchtet);
20947 wrktets[0] = searchtet;
20948 for (i = 0; i < 2; i++) {
20949 fnext(wrktets[i], wrktets[i+1]);
20951 if (apex(wrktets[0]) == oppo(wrktets[2])) {
20957 }
else if (vt == FREEFACETVERTEX) {
20959 point2tetorg(steinerpt, searchtet);
20962 wrktets[0] = searchtet;
20963 wrktets[1] = searchtet;
20964 esymself(wrktets[1]);
20965 enextself(wrktets[1]);
20966 wrktets[2] = searchtet;
20967 eprevself(wrktets[2]);
20968 esymself(wrktets[2]);
20971 searchtet.tet = NULL;
20972 for (i = 0; i < 3; i++) {
20973 spintet = wrktets[i];
20977 fnextself(spintet);
20978 if (spintet.tet == wrktets[i].tet)
break;
20980 if (valence == 3) {
20982 searchtet = wrktets[i];
20995 if (vt == FREESEGVERTEX) {
20999 sstpivot1(leftseg, searchtet);
21000 if (org(searchtet) != steinerpt) {
21001 esymself(searchtet);
21003 spintet = searchtet;
21006 eprev(spintet, neightet);
21007 esymself(neightet);
21009 fsymself(neightet);
21010 if (oppo(neightet) != rpt) {
21016 point chkp1 = org(neightet);
21017 point chkp2 = apex(neightet);
21018 REAL chkori = orient3d(rpt, lpt, chkp1, chkp2);
21019 if (chkori >= 0.0) {
21024 fnextself(spintet);
21025 if (spintet.tet == searchtet.tet) {
21036 if (vt == FREESEGVERTEX) {
21038 if (getedge(lpt, rpt, &searchtet)) {
21041 if (!checksubfaceflag) {
21046 for (i = 0; i < 2; i++) {
21047 checkseg = (i == 0) ? leftseg : rightseg;
21048 sstpivot1(checkseg, neightet);
21049 spintet = neightet;
21051 tssdissolve1(spintet);
21052 fnextself(spintet);
21053 if (spintet.tet == neightet.tet)
break;
21055 sstdissolve1(checkseg);
21058 spivot(rightseg, parentsh);
21059 sremovevertex(steinerpt, &parentsh, &rightseg, slawson);
21061 caveshbdlist->restart();
21063 sstbond1(rightseg, searchtet);
21064 spintet = searchtet;
21066 tssbond1(spintet, rightseg);
21067 fnextself(spintet);
21068 if (spintet.tet == searchtet.tet)
break;
21071 setpointtype(steinerpt, FREEVOLVERTEX);
21084 if (vt == FREESEGVERTEX) {
21086 for (i = 0; i < 2; i++) {
21087 checkseg = (i == 0) ? leftseg : rightseg;
21088 sstpivot1(checkseg, neightet);
21089 spintet = neightet;
21091 tssdissolve1(spintet);
21092 fnextself(spintet);
21093 if (spintet.tet == neightet.tet)
break;
21095 sstdissolve1(checkseg);
21097 if (checksubfaceflag) {
21099 for (i = 0; i < 2; i++) {
21100 checkseg = (i == 0) ? leftseg : rightseg;
21101 spivot(checkseg, parentsh);
21102 if (parentsh.sh != NULL) {
21105 stpivot(spinsh, neightet);
21106 if (neightet.tet != NULL) {
21107 tsdissolve(neightet);
21110 stpivot(spinsh, neightet);
21111 if (neightet.tet != NULL) {
21112 tsdissolve(neightet);
21114 stdissolve(spinsh);
21115 spivotself(spinsh);
21116 if (spinsh.sh == parentsh.sh)
break;
21123 if (loc == INTETRAHEDRON) {
21125 fliptets =
new triface[4];
21126 fliptets[0] = searchtet;
21127 for (i = 0; i < 2; i++) {
21128 fnext(fliptets[i], fliptets[i+1]);
21130 eprev(fliptets[0], fliptets[3]);
21131 fnextself(fliptets[3]);
21132 eprevself(fliptets[3]);
21133 esymself(fliptets[3]);
21171 if (vt == FREEFACETVERTEX) {
21174 triface checktet, chkface;
21175 for (i = 0; i < 3; i++) {
21176 enext(fliptets[i], checktet);
21177 esymself(checktet);
21178 int scount = 0;
int k;
21179 for (k = 0; k < 3; k++) {
21180 esym(checktet, chkface);
21181 if (issubface(chkface)) scount++;
21182 enextself(checktet);
21186 }
else if (scount == 2) {
21189 delete [] fliptets;
21196 for (i = 0; i < 3; i++) {
21197 eprev(fliptets[i], checktet);
21198 esymself(checktet);
21199 if (issubface(chkface)) scount++;
21203 delete [] fliptets;
21208 flip41(fliptets, 1, &fc);
21210 }
else if (loc == ONFACE) {
21214 fliptets =
new triface[6];
21215 fliptets[0] = searchtet;
21216 for (i = 0; i < 2; i++) {
21217 fnext(fliptets[i], fliptets[i+1]);
21219 eprev(fliptets[0], fliptets[3]);
21220 fnextself(fliptets[3]);
21221 esymself(fliptets[3]);
21222 eprevself(fliptets[3]);
21223 for (i = 3; i < 5; i++) {
21224 fnext(fliptets[i], fliptets[i+1]);
21226 if (vt == FREEFACETVERTEX) {
21229 for (i = 3; i < 6; i++) {
21230 if (issubface(fliptets[i])) valence++;
21235 for (i = 0; i < 3; i++) {
21236 esym(fliptets[i+3], wrktets[i]);
21237 esym(fliptets[i], fliptets[i+3]);
21238 fliptets[i] = wrktets[i];
21241 wrktets[1] = fliptets[1];
21242 fliptets[1] = fliptets[2];
21243 fliptets[2] = wrktets[1];
21244 wrktets[1] = fliptets[4];
21245 fliptets[4] = fliptets[5];
21246 fliptets[5] = wrktets[1];
21250 triface checktet, chkface;
21251 for (i = 0; i < 3; i++) {
21252 enext(fliptets[i], checktet);
21253 esymself(checktet);
21254 int scount = 0;
int k;
21255 for (k = 0; k < 3; k++) {
21256 esym(checktet, chkface);
21257 if (issubface(chkface)) scount++;
21258 enextself(checktet);
21262 }
else if (scount == 2) {
21265 delete [] fliptets;
21272 for (i = 0; i < 3; i++) {
21273 eprev(fliptets[i], checktet);
21274 esymself(checktet);
21275 if (issubface(chkface)) scount++;
21279 delete [] fliptets;
21292 flip32(&(fliptets[3]), 1, &fc);
21296 flip41(fliptets, 1, &fc);
21298 }
else if (loc == ONEDGE) {
21304 spintet = searchtet;
21307 fnextself(spintet);
21308 if (spintet.tet == searchtet.tet)
break;
21311 fliptets =
new triface[2 * n];
21312 fliptets[0] = searchtet;
21313 for (i = 0; i < (n - 1); i++) {
21314 fnext(fliptets[i], fliptets[i+1]);
21316 eprev(fliptets[0], fliptets[n]);
21317 fnextself(fliptets[n]);
21318 esymself(fliptets[n]);
21319 eprevself(fliptets[n]);
21320 for (i = n; i < (2 * n - 1); i++) {
21321 fnext(fliptets[i], fliptets[i+1]);
21331 wrktets[0] = fliptets[0];
21332 eprevself(wrktets[0]);
21333 esymself(wrktets[0]);
21334 enextself(wrktets[0]);
21335 wrktets[1] = fliptets[n];
21336 enextself(wrktets[1]);
21337 esymself(wrktets[1]);
21338 eprevself(wrktets[1]);
21340 flip23(wrktets, 1, &fc);
21342 fliptets[n] = wrktets[2];
21344 fliptets[0] = wrktets[0];
21353 for (i = 1; i < (n - 1); i++) {
21354 wrktets[0] = wrktets[1];
21355 enextself(wrktets[0]);
21356 esymself(wrktets[0]);
21357 eprevself(wrktets[0]);
21358 wrktets[1] = fliptets[n+i];
21359 enextself(wrktets[1]);
21360 wrktets[2] = fliptets[i];
21361 eprevself(wrktets[2]);
21362 esymself(wrktets[2]);
21364 flip32(wrktets, 1, &fc);
21366 fliptets[i] = wrktets[0];
21367 esymself(fliptets[i]);
21377 wrktets[3] = wrktets[1];
21378 wrktets[0] = fliptets[n];
21379 eprevself(wrktets[0]);
21380 esymself(wrktets[0]);
21381 enextself(wrktets[0]);
21382 wrktets[1] = fliptets[n-1];
21383 esymself(wrktets[1]);
21384 enextself(wrktets[1]);
21385 wrktets[2] = fliptets[2*n-1];
21386 enextself(wrktets[2]);
21387 esymself(wrktets[2]);
21388 enextself(wrktets[2]);
21390 flip41(wrktets, 1, &fc);
21392 fliptets[n-1] = wrktets[0];
21396 delete [] fliptets;
21398 if (vt == FREESEGVERTEX) {
21403 slawson = (checksubfaceflag ? 0 : 1);
21404 spivot(rightseg, parentsh);
21405 sremovevertex(steinerpt, &parentsh, &rightseg, slawson);
21408 rightseg.shver = 0;
21410 point2tetorg(lpt, searchtet);
21411 finddirection(&searchtet, rpt);
21412 sstbond1(rightseg, searchtet);
21413 spintet = searchtet;
21415 tssbond1(spintet, rightseg);
21416 fnextself(spintet);
21417 if (spintet.tet == searchtet.tet)
break;
21420 if (checksubfaceflag) {
21422 spivot(rightseg, parentsh);
21423 if (parentsh.sh != NULL) {
21426 if (sorg(spinsh) != lpt) {
21429 apexpt = sapex(spinsh);
21431 spintet = searchtet;
21433 if (apex(spintet) == apexpt) {
21434 tsbond(spintet, spinsh);
21436 fsym(spintet, neightet);
21437 tsbond(neightet, spinsh);
21441 fnextself(spintet);
21443 spivotself(spinsh);
21444 if (spinsh.sh == parentsh.sh)
break;
21450 caveshbdlist->restart();
21454 if (pointtype(steinerpt) != UNUSEDVERTEX) {
21455 setpointtype(steinerpt, UNUSEDVERTEX);
21458 if (vt != VOLVERTEX) {
21460 if (vt == FREESEGVERTEX) {
21462 }
else if (vt == FREEFACETVERTEX) {
21464 }
else if (vt == FREEVOLVERTEX) {
21467 if (steinerleft > 0) steinerleft++;
21479 int tetgenmesh::suppressbdrysteinerpoint(point steinerpt)
21481 face parentsh, spinsh, *parysh;
21482 face leftseg, rightseg;
21483 point lpt = NULL, rpt = NULL;
21486 verttype vt = pointtype(steinerpt);
21488 if (vt == FREESEGVERTEX) {
21489 sdecode(point2sh(steinerpt), leftseg);
21491 if (sdest(leftseg) == steinerpt) {
21492 senext(leftseg, rightseg);
21493 spivotself(rightseg);
21494 rightseg.shver = 0;
21496 rightseg = leftseg;
21497 senext2(rightseg, leftseg);
21498 spivotself(leftseg);
21501 lpt = sorg(leftseg);
21502 rpt = sdest(rightseg);
21503 if (b->verbose > 2) {
21504 printf(
" Suppressing Steiner point %d in segment (%d, %d).\n",
21505 pointmark(steinerpt), pointmark(lpt), pointmark(rpt));
21508 spivot(leftseg, parentsh);
21509 if (parentsh.sh != NULL) {
21513 cavesegshlist->newindex((
void **) &parysh);
21516 if (sorg(*parysh)!= sorg(parentsh)) sesymself(*parysh);
21517 spivotself(spinsh);
21518 if (spinsh.sh == NULL)
break;
21519 if (spinsh.sh == parentsh.sh)
break;
21522 if (cavesegshlist->objects < 2) {
21524 cavesegshlist->restart();
21527 }
else if (vt == FREEFACETVERTEX) {
21528 if (b->verbose > 2) {
21529 printf(
" Suppressing Steiner point %d from facet.\n",
21530 pointmark(steinerpt));
21532 sdecode(point2sh(steinerpt), parentsh);
21534 for (i = 0; i < 2; i++) {
21535 cavesegshlist->newindex((
void **) &parysh);
21536 *parysh = parentsh;
21537 sesymself(parentsh);
21543 triface searchtet, neightet, *parytet;
21544 point pa, pb, pc, pd;
21545 REAL v1[3], v2[3], len, u;
21547 REAL startpt[3] = {0,}, samplept[3] = {0,}, candpt[3] = {0,};
21548 REAL ori, minvol, smallvol;
21552 int n = (int) cavesegshlist->objects;
21553 point *newsteiners =
new point[n];
21554 for (i = 0; i < n; i++) newsteiners[i] = NULL;
21557 for (i = 0; i < cavesegshlist->objects; i++) {
21558 parysh = (face *) fastlookup(cavesegshlist, i);
21559 stpivot(*parysh, searchtet);
21561 if (ishulltet(searchtet))
continue;
21565 setpoint2tet(steinerpt, encode(searchtet));
21566 getvertexstar(0, steinerpt, cavetetlist, NULL, caveshlist);
21568 pa = sorg(*parysh);
21569 pb = sdest(*parysh);
21570 pc = sapex(*parysh);
21571 facenormal(pa, pb, pc, v1, 1, NULL);
21572 len = sqrt(dot(v1, v1));
21576 if (vt == FREESEGVERTEX) {
21577 parysh = (face *) fastlookup(cavesegshlist, (i + 1) % n);
21578 pd = sapex(*parysh);
21579 facenormal(pb, pa, pd, v2, 1, NULL);
21580 len = sqrt(dot(v2, v2));
21585 v1[0] = 0.5 * (v1[0] + v2[0]);
21586 v1[1] = 0.5 * (v1[1] + v2[1]);
21587 v1[2] = 0.5 * (v1[2] + v2[2]);
21592 len = distance(pa, pb);
21593 v2[0] = steinerpt[0] + len * v1[0];
21594 v2[1] = steinerpt[1] + len * v1[1];
21595 v2[2] = steinerpt[2] + len * v1[2];
21596 for (j = 0; j < cavetetlist->objects; j++) {
21597 parytet = (triface *) fastlookup(cavetetlist, j);
21598 pa = org(*parytet);
21599 pb = dest(*parytet);
21600 pc = apex(*parytet);
21604 ori = orient3d(steinerpt, pa, pb, v2);
21606 ori = orient3d(steinerpt, pb, pc, v2);
21608 ori = orient3d(steinerpt, pc, pa, v2);
21611 planelineint(pa, pb, pc, steinerpt, v2, startpt, &u);
21617 if (j == cavetetlist->objects) {
21621 for (j = 0; j < caveshlist->objects; j++) {
21622 parysh = (face *) fastlookup(caveshlist, j);
21623 stpivot(*parysh, neightet);
21624 cavetetlist->newindex((
void **) &parytet);
21625 *parytet = neightet;
21630 v1[0] = steinerpt[0] - startpt[0];
21631 v1[1] = steinerpt[1] - startpt[1];
21632 v1[2] = steinerpt[2] - startpt[2];
21635 for (j = 1; j < samplesize - 1; j++) {
21636 samplept[0] = startpt[0] + ((REAL) j / (REAL) samplesize) * v1[0];
21637 samplept[1] = startpt[1] + ((REAL) j / (REAL) samplesize) * v1[1];
21638 samplept[2] = startpt[2] + ((REAL) j / (REAL) samplesize) * v1[2];
21641 for (k = 0; k < cavetetlist->objects; k++) {
21642 parytet = (triface *) fastlookup(cavetetlist, k);
21643 pa = org(*parytet);
21644 pb = dest(*parytet);
21645 pc = apex(*parytet);
21646 ori = orient3d(pb, pa, pc, samplept);
21649 REAL lab = distance(pa, pb);
21650 REAL lbc = distance(pb, pc);
21651 REAL lca = distance(pc, pa);
21652 REAL lv = (lab + lbc + lca) / 3.0;
21653 REAL l3 = lv*lv*lv;
21654 if (fabs(ori) / l3 < 1e-8) ori = 0.0;
21659 if (smallvol == -1) {
21662 if (ori < smallvol) smallvol = ori;
21665 if (k == cavetetlist->objects) {
21667 if (minvol == -1.0) {
21668 candpt[0] = samplept[0];
21669 candpt[1] = samplept[1];
21670 candpt[2] = samplept[2];
21673 if (minvol < smallvol) {
21675 candpt[0] = samplept[0];
21676 candpt[1] = samplept[1];
21677 candpt[2] = samplept[2];
21688 if (minvol > 0)
break;
21692 if (minvol == -1.0) {
21694 cavetetlist->restart();
21695 caveshlist->restart();
21699 makepoint(&(newsteiners[i]), FREEVOLVERTEX);
21700 newsteiners[i][0] = candpt[0];
21701 newsteiners[i][1] = candpt[1];
21702 newsteiners[i][2] = candpt[2];
21703 cavetetlist->restart();
21704 caveshlist->restart();
21707 if (i < cavesegshlist->objects) {
21709 for (; i > 0; i--) {
21710 if (newsteiners[i - 1] != NULL) {
21711 pointdealloc(newsteiners[i - 1]);
21714 delete [] newsteiners;
21715 cavesegshlist->restart();
21720 triface newtet, newface, spintet;
21721 face newsh, neighsh;
21722 face *splitseg, checkseg;
21726 if (vt == FREESEGVERTEX) {
21729 sstpivot1(leftseg, neightet);
21730 spintet = neightet;
21732 tssdissolve1(spintet);
21733 fnextself(spintet);
21734 if (spintet.tet == neightet.tet)
break;
21736 sstpivot1(rightseg, neightet);
21737 spintet = neightet;
21739 tssdissolve1(spintet);
21740 fnextself(spintet);
21741 if (spintet.tet == neightet.tet)
break;
21748 for (i = 0; i < cavesegshlist->objects; i++) {
21749 parysh = (face *) fastlookup(cavesegshlist, i);
21751 stpivot(*parysh, neightet);
21753 setpoint2tet(steinerpt, encode(neightet));
21754 getvertexstar(0, steinerpt, cavetetlist, NULL, caveshlist);
21755 if (!ishulltet(neightet)) {
21757 for (j = 0; j < cavetetlist->objects; j++) {
21758 parytet = (triface *) fastlookup(cavetetlist, j);
21759 setoppo(*parytet, newsteiners[i]);
21762 parytet = (triface *) fastlookup(cavetetlist, 0);
21763 setpoint2tet(newsteiners[i], (tetrahedron) (parytet->tet));
21765 if (steinerleft > 0) steinerleft--;
21769 for (j = 0; j < caveshlist->objects; j++) {
21771 parysh = (face *) fastlookup(caveshlist, j);
21772 stpivot(*parysh, neightet);
21775 dissolve(neightet);
21776 tsdissolve(neightet);
21779 cavetetlist->restart();
21780 caveshlist->restart();
21782 cavesegshlist->restart();
21784 if (vt == FREESEGVERTEX) {
21785 spivot(rightseg, parentsh);
21786 splitseg = &rightseg;
21788 if (sdest(parentsh) == steinerpt) {
21789 senextself(parentsh);
21790 }
else if (sapex(parentsh) == steinerpt) {
21791 senext2self(parentsh);
21795 sremovevertex(steinerpt, &parentsh, splitseg, slawson);
21797 if (vt == FREESEGVERTEX) {
21799 rightseg.shver = 0;
21804 for (i = 0; i < caveshbdlist->objects; i++) {
21805 parysh = (face *) fastlookup(caveshbdlist, i);
21811 maketetrahedron(&newtet);
21812 maketetrahedron(&neightet);
21813 setvertices(newtet, pa, pb, pc, dummypoint);
21814 setvertices(neightet, pb, pa, pc, dummypoint);
21815 bond(newtet, neightet);
21816 tsbond(newtet, newsh);
21818 tsbond(neightet, newsh);
21821 hullsize += (caveshbdlist->objects * 2l);
21823 if (vt == FREESEGVERTEX) {
21825 spivot(rightseg, parentsh);
21828 if (sorg(spinsh) != lpt) sesymself(spinsh);
21830 stpivot(spinsh, newtet);
21831 tssbond1(newtet, rightseg);
21833 spivot(spinsh, neighsh);
21834 if (sorg(neighsh) != lpt) sesymself(neighsh);
21835 sesymself(neighsh);
21836 stpivot(neighsh, neightet);
21837 tssbond1(neightet, rightseg);
21838 sstbond1(rightseg, neightet);
21841 esymself(neightet);
21843 bond(newtet, neightet);
21845 spivotself(spinsh);
21846 if (spinsh.sh == parentsh.sh)
break;
21851 for (i = 0; i < caveshbdlist->objects; i++) {
21852 parysh = (face *) fastlookup(caveshbdlist, i);
21856 for (k = 0; k < 2; k++) {
21857 stpivot(newsh, newtet);
21858 for (j = 0; j < 3; j++) {
21860 esym(newtet, newface);
21861 if (newface.tet[newface.ver & 3] == NULL) {
21863 sspivot(newsh, checkseg);
21864 if (checkseg.sh != NULL) {
21866 tssbond1(newtet, checkseg);
21867 sstbond1(checkseg, newtet);
21869 spivot(newsh, neighsh);
21870 if (neighsh.sh != NULL) {
21872 if (sorg(neighsh) != sdest(newsh)) sesymself(neighsh);
21873 stpivot(neighsh, neightet);
21874 if (sinfected(neighsh)) {
21875 esymself(neightet);
21878 spintet = neightet;
21880 esym(spintet, searchtet);
21881 fsym(searchtet, spintet);
21882 if (spintet.tet == NULL)
break;
21885 neightet = searchtet;
21890 sstpivot1(checkseg, neightet);
21891 if (org(neightet) != sdest(newsh)) esymself(neightet);
21893 spintet = neightet;
21895 esym(spintet, searchtet);
21896 fsym(searchtet, spintet);
21897 if (spintet.tet == NULL)
break;
21900 neightet = searchtet;
21902 pc = apex(newface);
21903 if (apex(neightet) == steinerpt) {
21906 caveoldtetlist->newindex((
void **) &parytet);
21907 *parytet = neightet;
21910 fnextself(neightet);
21912 if (pc == dummypoint) {
21913 if (apex(neightet) != dummypoint) {
21914 setapex(newface, apex(neightet));
21920 bond(newface, neightet);
21930 for (i = 0; i < caveshbdlist->objects; i++) {
21931 parysh = (face *) fastlookup(caveshbdlist, i);
21932 suninfect(*parysh);
21934 caveshbdlist->restart();
21936 if (caveoldtetlist->objects > 0l) {
21938 for (i = 0; i < caveoldtetlist->objects; i++) {
21939 parytet = (triface *) fastlookup(caveoldtetlist, i);
21940 tetrahedrondealloc(parytet->tet);
21943 hullsize -= caveoldtetlist->objects;
21944 caveoldtetlist->restart();
21947 setpointtype(steinerpt, UNUSEDVERTEX);
21949 if (vt == FREESEGVERTEX) {
21954 if (steinerleft > 0) steinerleft++;
21958 int steinercount = 0;
21960 int bak_fliplinklevel = b->fliplinklevel;
21961 b->fliplinklevel = 100000;
21964 for (i = 0; i < n; i++) {
21965 if (newsteiners[i] != NULL) {
21966 if (!removevertexbyflips(newsteiners[i])) {
21967 if (b->supsteiner_level > 0) {
21969 subvertstack->newindex((
void **) &parypt);
21970 *parypt = newsteiners[i];
21977 b->fliplinklevel = bak_fliplinklevel;
21979 if (steinercount > 0) {
21980 if (b->verbose > 2) {
21981 printf(
" Added %d interior Steiner points.\n", steinercount);
21985 delete [] newsteiners;
22001 int tetgenmesh::suppresssteinerpoints()
22005 printf(
"Suppressing Steiner points ...\n");
22008 point rempt, *parypt;
22010 int bak_fliplinklevel = b->fliplinklevel;
22011 b->fliplinklevel = 100000;
22012 int suppcount = 0, remcount = 0;
22016 for (i = 0; i < subvertstack->objects; i++) {
22017 parypt = (point *) fastlookup(subvertstack, i);
22019 if (pointtype(rempt) != UNUSEDVERTEX) {
22020 if ((pointtype(rempt) == FREESEGVERTEX) ||
22021 (pointtype(rempt) == FREEFACETVERTEX)) {
22022 if (suppressbdrysteinerpoint(rempt)) {
22029 if (suppcount > 0) {
22031 printf(
" Suppressed %d boundary Steiner points.\n", suppcount);
22035 if (b->supsteiner_level > 0) {
22036 for (i = 0; i < subvertstack->objects; i++) {
22037 parypt = (point *) fastlookup(subvertstack, i);
22039 if (pointtype(rempt) != UNUSEDVERTEX) {
22040 if (pointtype(rempt) == FREEVOLVERTEX) {
22041 if (removevertexbyflips(rempt)) {
22049 if (remcount > 0) {
22051 printf(
" Removed %d interior Steiner points.\n", remcount);
22055 b->fliplinklevel = bak_fliplinklevel;
22057 if (b->supsteiner_level > 1) {
22063 int smtcount, count, ivcount;
22067 opm.max_min_volume = 1;
22068 opm.numofsearchdirs = 20;
22069 opm.searchstep = 0.001;
22082 for (i = 0; i < subvertstack->objects; i++) {
22083 parypt = (point *) fastlookup(subvertstack, i);
22085 if (pointtype(rempt) == FREEVOLVERTEX) {
22086 getvertexstar(1, rempt, cavetetlist, NULL, NULL);
22088 for (j = 0; j < cavetetlist->objects; j++) {
22089 parytet = (triface *) fastlookup(cavetetlist, j);
22090 ppt = (point *) &(parytet->tet[4]);
22091 ori = orient3dfast(ppt[1], ppt[0], ppt[2], ppt[3]);
22095 if (opm.initval > ori) opm.initval = ori;
22098 if (smoothpoint(rempt, cavetetlist, 1, &opm)) {
22101 if (opm.imprval <= 0.0) {
22104 cavetetlist->restart();
22123 if (opm.maxiter > 0) {
22125 opm.numofsearchdirs = 30;
22126 opm.searchstep = 0.0001;
22136 printf(
"BUG Report! The mesh contain inverted elements.\n");
22140 if (smtcount > 0) {
22141 printf(
" Smoothed %d Steiner points.\n", smtcount);
22146 subvertstack->restart();
22157 void tetgenmesh::recoverboundary(clock_t& tv)
22159 arraypool *misseglist, *misshlist;
22160 arraypool *bdrysteinerptlist;
22161 face searchsh, *parysh;
22162 face searchseg, *paryseg;
22163 point rempt, *parypt;
22169 long bak_segref_count, bak_facref_count, bak_volref_count;
22172 printf(
"Recovering boundaries...\n");
22177 printf(
" Recovering segments.\n");
22181 checksubsegflag = 1;
22183 misseglist =
new arraypool(
sizeof(face), 8);
22184 bdrysteinerptlist =
new arraypool(
sizeof(point), 8);
22187 subsegs->traversalinit();
22188 for (i = 0; i < subsegs->items; i++) {
22189 s = randomnation(i + 1);
22191 subsegstack->newindex((
void **) &paryseg);
22192 *paryseg = * (face *) fastlookup(subsegstack, s);
22194 searchseg.sh = shellfacetraverse(subsegs);
22195 paryseg = (face *) fastlookup(subsegstack, s);
22196 *paryseg = searchseg;
22200 ms = subsegs->items;
22202 if (b->fliplinklevel < 0) {
22203 autofliplinklevel = 1;
22208 recoversegments(misseglist, 0, 0);
22210 if (misseglist->objects > 0) {
22211 if (b->fliplinklevel >= 0) {
22214 if (misseglist->objects >= ms) {
22219 b->fliplinklevel = 100000;
22222 ms = misseglist->objects;
22227 for (i = 0; i < misseglist->objects; i++) {
22228 subsegstack->newindex((
void **) &paryseg);
22229 *paryseg = * (face *) fastlookup(misseglist, i);
22231 misseglist->restart();
22232 autofliplinklevel+=b->fliplinklevelinc;
22241 printf(
" %ld (%ld) segments are recovered (missing).\n",
22242 subsegs->items - misseglist->objects, misseglist->objects);
22245 if (misseglist->objects > 0) {
22247 while (misseglist->objects > 0) {
22248 ms = misseglist->objects;
22249 for (i = 0; i < misseglist->objects; i++) {
22250 subsegstack->newindex((
void **) &paryseg);
22251 *paryseg = * (face *) fastlookup(misseglist, i);
22253 misseglist->restart();
22255 recoversegments(misseglist, 1, 0);
22257 if (misseglist->objects < ms) {
22265 printf(
" %ld (%ld) segments are recovered (missing).\n",
22266 subsegs->items - misseglist->objects, misseglist->objects);
22270 if (misseglist->objects > 0) {
22273 while (misseglist->objects > 0) {
22274 ms = misseglist->objects;
22275 for (i = 0; i < misseglist->objects; i++) {
22276 subsegstack->newindex((
void **) &paryseg);
22277 *paryseg = * (face *) fastlookup(misseglist, i);
22279 misseglist->restart();
22281 recoversegments(misseglist, 1, 1);
22283 if (misseglist->objects < ms) {
22291 printf(
" Added %ld Steiner points in volume.\n", st_volref_count);
22295 if (misseglist->objects > 0) {
22298 long bak_inpoly_count = st_volref_count;
22299 for (i = 0; i < misseglist->objects; i++) {
22300 subsegstack->newindex((
void **) &paryseg);
22301 *paryseg = * (face *) fastlookup(misseglist, i);
22303 misseglist->restart();
22305 recoversegments(misseglist, 1, 2);
22308 printf(
" Added %ld Steiner points in segments.\n", st_segref_count);
22309 if (st_volref_count > bak_inpoly_count) {
22310 printf(
" Added another %ld Steiner points in volume.\n",
22311 st_volref_count - bak_inpoly_count);
22317 if (st_segref_count > 0) {
22319 bak_segref_count = st_segref_count;
22320 bak_volref_count = st_volref_count;
22321 for (i = 0; i < subvertstack->objects; i++) {
22323 parypt = (point *) fastlookup(subvertstack, i);
22325 if (!removevertexbyflips(rempt)) {
22327 bdrysteinerptlist->newindex((
void **) &parypt);
22332 if (st_segref_count < bak_segref_count) {
22333 if (bak_volref_count < st_volref_count) {
22334 printf(
" Suppressed %ld Steiner points in segments.\n",
22335 st_volref_count - bak_volref_count);
22337 if ((st_segref_count + (st_volref_count - bak_volref_count)) <
22338 bak_segref_count) {
22339 printf(
" Removed %ld Steiner points in segments.\n",
22341 (st_segref_count + (st_volref_count - bak_volref_count)));
22345 subvertstack->restart();
22352 printf(
" Recovering facets.\n");
22356 checksubfaceflag = 1;
22358 misshlist =
new arraypool(
sizeof(face), 8);
22361 subfaces->traversalinit();
22362 for (i = 0; i < subfaces->items; i++) {
22363 s = randomnation(i + 1);
22365 subfacstack->newindex((
void **) &parysh);
22366 *parysh = * (face *) fastlookup(subfacstack, s);
22368 searchsh.sh = shellfacetraverse(subfaces);
22369 parysh = (face *) fastlookup(subfacstack, s);
22370 *parysh = searchsh;
22373 ms = subfaces->items;
22375 b->fliplinklevel = -1;
22376 if (b->fliplinklevel < 0) {
22377 autofliplinklevel = 1;
22381 recoversubfaces(misshlist, 0);
22383 if (misshlist->objects > 0) {
22384 if (b->fliplinklevel >= 0) {
22387 if (misshlist->objects >= ms) {
22392 b->fliplinklevel = 100000;
22395 ms = misshlist->objects;
22400 for (i = 0; i < misshlist->objects; i++) {
22401 subfacstack->newindex((
void **) &parysh);
22402 *parysh = * (face *) fastlookup(misshlist, i);
22404 misshlist->restart();
22405 autofliplinklevel+=b->fliplinklevelinc;
22414 printf(
" %ld (%ld) subfaces are recovered (missing).\n",
22415 subfaces->items - misshlist->objects, misshlist->objects);
22418 if (misshlist->objects > 0) {
22420 for (i = 0; i < misshlist->objects; i++) {
22421 subfacstack->newindex((
void **) &parysh);
22422 *parysh = * (face *) fastlookup(misshlist, i);
22424 misshlist->restart();
22426 recoversubfaces(NULL, 1);
22429 printf(
" Added %ld Steiner points in facets.\n", st_facref_count);
22434 if (st_facref_count > 0) {
22436 bak_facref_count = st_facref_count;
22437 for (i = 0; i < subvertstack->objects; i++) {
22439 parypt = (point *) fastlookup(subvertstack, i);
22441 if (!removevertexbyflips(*parypt)) {
22443 bdrysteinerptlist->newindex((
void **) &parypt);
22448 if (st_facref_count < bak_facref_count) {
22449 printf(
" Removed %ld Steiner points in facets.\n",
22450 bak_facref_count - st_facref_count);
22453 subvertstack->restart();
22457 if (bdrysteinerptlist->objects > 0) {
22459 printf(
" %ld Steiner points remained in boundary.\n",
22460 bdrysteinerptlist->objects);
22466 totalworkmemory += (misseglist->totalmemory + misshlist->totalmemory +
22467 bdrysteinerptlist->totalmemory);
22469 delete bdrysteinerptlist;
22490 void tetgenmesh::carveholes()
22492 arraypool *tetarray, *hullarray;
22493 triface tetloop, neightet, *parytet, *parytet1;
22494 triface *regiontets = NULL;
22495 face checksh, *parysh;
22497 point ptloop, *parypt;
22503 printf(
"Marking exterior tetrahedra ...\n");
22505 printf(
"Removing exterior tetrahedra ...\n");
22510 tetarray =
new arraypool(
sizeof(triface), 10);
22511 hullarray =
new arraypool(
sizeof(triface), 10);
22514 tetrahedrons->traversalinit();
22516 tetloop.tet = alltetrahedrontraverse();
22517 while (tetloop.tet != (tetrahedron *) NULL) {
22518 if (ishulltet(tetloop)) {
22520 if (!issubface(tetloop)) {
22523 hullarray->newindex((
void **) &parytet);
22524 *parytet = tetloop;
22526 decode(tetloop.tet[3], neightet);
22527 if (!infected(neightet)) {
22529 tetarray->newindex((
void **) &parytet);
22530 *parytet = neightet;
22534 tetloop.tet = alltetrahedrontraverse();
22537 if (in->numberofholes > 0) {
22539 for (i = 0; i < 3 * in->numberofholes; i += 3) {
22541 neightet.tet = NULL;
22542 randomsample(&(in->holelist[i]), &neightet);
22543 if (locate(&(in->holelist[i]), &neightet) != OUTSIDE) {
22545 if (!infected(neightet)) {
22547 tetarray->newindex((
void **) &parytet);
22548 *parytet = neightet;
22550 if (!issubface(neightet)) {
22551 decode(neightet.tet[neightet.ver & 3], tetloop);
22552 if (!infected(tetloop)) {
22554 if (ishulltet(tetloop)) {
22555 hullarray->newindex((
void **) &parytet);
22557 tetarray->newindex((
void **) &parytet);
22559 *parytet = tetloop;
22564 decode(neightet.tet[neightet.ver & 3], tetloop);
22565 if (ishulltet(tetloop)) {
22568 if (!infected(tetloop)) {
22570 hullarray->newindex((
void **) &parytet);
22571 *parytet = tetloop;
22574 if (infected(tetloop)) {
22576 tspivot(neightet, checksh);
22578 subfacstack->newindex((
void **) &parysh);
22586 printf(
"Warning: The %d-th hole point ", i/3 + 1);
22587 printf(
"lies outside the convex hull.\n");
22593 if (b->hole_mesh && (b->hole_mesh_filename[0] != 0)) {
22596 char filebasename[256];
22597 strcpy(filebasename, b->hole_mesh_filename);
22599 if (!strcmp(&filebasename[strlen(filebasename) - 4],
".ele")) {
22600 filebasename[strlen(filebasename) - 4] =
'\0';
22603 bool hole_mesh_loaded =
false;
22605 if (io.load_node(filebasename)) {
22606 if (io.load_tet(filebasename)) {
22607 hole_mesh_loaded =
true;
22610 if (hole_mesh_loaded) {
22612 printf(
" Adding hole tets from the mesh %s\n", b->hole_mesh_filename);
22614 int count = 0, hcount = 0, scount = 0;
22615 int shift = io.firstnumber > 0 ? -1 : 0;
22616 double *p1, *p2, *p3, *p4;
22617 double searchpt[3];
22618 for (i = 0; i < io.numberoftetrahedra; i++) {
22619 int *idx = &(io.tetrahedronlist[i * 4]);
22620 p1 = &(io.pointlist[(idx[0]+shift)*3]);
22621 p2 = &(io.pointlist[(idx[1]+shift)*3]);
22622 p3 = &(io.pointlist[(idx[2]+shift)*3]);
22623 p4 = &(io.pointlist[(idx[3]+shift)*3]);
22624 for (j = 0; j < 3; j++) {
22625 searchpt[j] = (p1[j]+p2[j]+p3[j]+p4[j])/4.;
22628 neightet.tet = NULL;
22629 if (locate(searchpt, &neightet) != OUTSIDE) {
22631 if (!infected(neightet)) {
22633 tetarray->newindex((
void **) &parytet);
22634 *parytet = neightet;
22637 if (!issubface(neightet)) {
22638 decode(neightet.tet[neightet.ver & 3], tetloop);
22639 if (!infected(tetloop)) {
22641 if (ishulltet(tetloop)) {
22642 hullarray->newindex((
void **) &parytet);
22645 tetarray->newindex((
void **) &parytet);
22648 *parytet = tetloop;
22653 decode(neightet.tet[neightet.ver & 3], tetloop);
22654 if (ishulltet(tetloop)) {
22657 if (!infected(tetloop)) {
22659 hullarray->newindex((
void **) &parytet);
22660 *parytet = tetloop;
22664 if (infected(tetloop)) {
22666 tspivot(neightet, checksh);
22668 subfacstack->newindex((
void **) &parysh);
22677 printf(
" Added %d hole tets, %d hull tet, %d hole subfaces\n",
22678 count, hcount, scount);
22683 if (b->regionattrib && (in->numberofregions > 0)) {
22686 regiontets =
new triface[in->numberofregions];
22688 for (i = 0; i < 5 * in->numberofregions; i += 5) {
22690 neightet.tet = NULL;
22691 randomsample(&(in->regionlist[i]), &neightet);
22692 if (locate(&(in->regionlist[i]), &neightet) != OUTSIDE) {
22693 regiontets[i/5] = neightet;
22696 printf(
"Warning: The %d-th region point ", i/5+1);
22697 printf(
"lies outside the convex hull.\n");
22699 regiontets[i/5].tet = NULL;
22705 for (i = 0; i < tetarray->objects; i++) {
22706 parytet = (triface *) fastlookup(tetarray, i);
22707 j = (parytet->ver & 3);
22709 for (k = 1; k < 4; k++) {
22710 decode(parytet->tet[(j + k) % 4], neightet);
22712 if (!infected(neightet)) {
22714 if (!issubface(neightet)) {
22717 tetarray->newindex((
void **) &parytet1);
22718 *parytet1 = neightet;
22721 if (ishulltet(neightet)) {
22724 hullarray->newindex((
void **) &parytet1);
22725 *parytet1 = neightet;
22727 tspivot(neightet, checksh);
22730 subfacstack->newindex((
void **) &parysh);
22737 if (issubface(neightet)) {
22738 tspivot(neightet, checksh);
22739 if (!sinfected(checksh)) {
22741 subfacstack->newindex((
void **) &parysh);
22749 if (b->regionattrib && (in->numberofregions > 0)) {
22751 for (i = 0; i < in->numberofregions; i++) {
22752 if (infected(regiontets[i])) {
22754 printf(
"Warning: The %d-th region point ", i+1);
22755 printf(
"lies in the exterior of the domain.\n");
22757 regiontets[i].tet = NULL;
22766 points->traversalinit();
22767 ptloop = pointtraverse();
22768 while (ptloop != NULL) {
22769 if ((pointtype(ptloop) != UNUSEDVERTEX) &&
22770 (pointtype(ptloop) != DUPLICATEDVERTEX)) {
22771 decode(point2tet(ptloop), neightet);
22772 if (infected(neightet)) {
22773 cavetetvertlist->newindex((
void **) &parypt);
22776 if (b->nobisect && (b->supsteiner_level > 0)) {
22778 if (pointmark(ptloop) >
22779 (in->numberofpoints - (in->firstnumber ? 0 : 1))) {
22780 subvertstack->newindex((
void **) &parypt);
22785 ptloop = pointtraverse();
22788 if (!b->convex && (tetarray->objects > 0l)) {
22790 arraypool *newhullfacearray;
22791 triface hulltet, casface;
22792 face segloop, *paryseg;
22794 long delsegcount = 0l;
22798 subsegs->traversalinit();
22799 segloop.sh = shellfacetraverse(subsegs);
22800 while (segloop.sh != NULL) {
22801 sstpivot1(segloop, neightet);
22802 if (infected(neightet)) {
22803 subsegstack->newindex((
void **) &paryseg);
22804 *paryseg = segloop;
22806 segloop.sh = shellfacetraverse(subsegs);
22809 newhullfacearray =
new arraypool(
sizeof(triface), 10);
22812 for (i = 0; i < tetarray->objects; i++) {
22813 parytet = (triface *) fastlookup(tetarray, i);
22814 for (j = 0; j < 4; j++) {
22815 decode(parytet->tet[j], tetloop);
22816 if (!infected(tetloop)) {
22818 tspivot(tetloop, checksh);
22819 maketetrahedron(&hulltet);
22821 pb = dest(tetloop);
22822 pc = apex(tetloop);
22823 setvertices(hulltet, pb, pa, pc, dummypoint);
22824 bond(tetloop, hulltet);
22826 sesymself(checksh);
22827 tsbond(hulltet, checksh);
22829 for (k = 0; k < 3; k++) {
22830 if (issubseg(tetloop)) {
22831 tsspivot1(tetloop, checkseg);
22832 tssbond1(hulltet, checkseg);
22833 sstbond1(checkseg, hulltet);
22835 enextself(tetloop);
22836 eprevself(hulltet);
22839 setpoint2tet(pa, (tetrahedron) tetloop.tet);
22840 setpoint2tet(pb, (tetrahedron) tetloop.tet);
22841 setpoint2tet(pc, (tetrahedron) tetloop.tet);
22844 newhullfacearray->newindex((
void **) &parytet1);
22845 parytet1->tet = parytet->tet;
22852 for (i = 0; i < newhullfacearray->objects; i++) {
22853 parytet = (triface *) fastlookup(newhullfacearray, i);
22854 fsym(*parytet, neightet);
22856 fsym(neightet, hulltet);
22857 for (j = 0; j < 3; j++) {
22858 esym(hulltet, casface);
22859 if (casface.tet[casface.ver & 3] == NULL) {
22863 neightet = *parytet;
22865 fnextself(neightet);
22866 if (!infected(neightet))
break;
22868 if (!ishulltet(neightet)) {
22870 fsymself(neightet);
22871 esymself(neightet);
22874 bond(casface, neightet);
22876 enextself(hulltet);
22877 enextself(*parytet);
22881 if (subfacstack->objects > 0l) {
22885 face casingout, casingin;
22887 for (i = 0; i < subfacstack->objects; i++) {
22888 parysh = (face *) fastlookup(subfacstack, i);
22891 printf(
"Warning: Removed an exterior face (%d, %d, %d) #%d\n",
22892 pointmark(sorg(*parysh)), pointmark(sdest(*parysh)),
22893 pointmark(sapex(*parysh)), shellmark(*parysh));
22897 for (j = 0; j < 3; j++) {
22898 spivot(*parysh, casingout);
22899 sspivot(*parysh, checkseg);
22900 if (casingout.sh != NULL) {
22901 casingin = casingout;
22903 spivot(casingin, checksh);
22904 if (checksh.sh == parysh->sh)
break;
22905 casingin = checksh;
22907 if (casingin.sh != casingout.sh) {
22909 sbond1(casingin, casingout);
22912 sdissolve(casingout);
22914 if (checkseg.sh != NULL) {
22916 ssbond(casingout, checkseg);
22919 if (checkseg.sh != NULL) {
22921 if (delsegcount == 0) {
22923 printf(
"Warning: Removed an exterior segment (%d, %d) #%d\n",
22924 pointmark(sorg(checkseg)), pointmark(sdest(checkseg)),
22925 shellmark(checkseg));
22928 shellfacedealloc(subsegs, checkseg.sh);
22932 senextself(*parysh);
22935 shellfacedealloc(subfaces, parysh->sh);
22938 printf(
" Deleted %ld subfaces.\n", subfacstack->objects);
22940 subfacstack->restart();
22943 if (subsegstack->objects > 0l) {
22944 for (i = 0; i < subsegstack->objects; i++) {
22945 paryseg = (face *) fastlookup(subsegstack, i);
22946 if (paryseg->sh && (paryseg->sh[3] != NULL)) {
22947 sstpivot1(*paryseg, neightet);
22948 if (infected(neightet)) {
22950 printf(
"Warning: Removed an exterior segment (%d, %d) #%d\n",
22951 pointmark(sorg(*paryseg)), pointmark(sdest(*paryseg)),
22952 shellmark(*paryseg));
22954 shellfacedealloc(subsegs, paryseg->sh);
22959 subsegstack->restart();
22962 if (delsegcount > 0) {
22964 printf(
" Deleted %ld segments.\n", delsegcount);
22968 if (cavetetvertlist->objects > 0l) {
22970 long delvertcount = unuverts;
22971 long delsteinercount = 0l;
22973 for (i = 0; i < cavetetvertlist->objects; i++) {
22974 parypt = (point *) fastlookup(cavetetvertlist, i);
22975 decode(point2tet(*parypt), neightet);
22976 if (infected(neightet)) {
22978 if (pointmark(*parypt) >
22979 (in->numberofpoints - (in->firstnumber ? 0 : 1))) {
22981 if (pointtype(*parypt) == FREESEGVERTEX) {
22983 }
else if (pointtype(*parypt) == FREEFACETVERTEX) {
22989 if (steinerleft > 0) steinerleft++;
22991 setpointtype(*parypt, UNUSEDVERTEX);
22997 if (unuverts > delvertcount) {
22998 if (delsteinercount > 0l) {
22999 if (unuverts > (delvertcount + delsteinercount)) {
23000 printf(
" Removed %ld exterior input vertices.\n",
23001 unuverts - delvertcount - delsteinercount);
23003 printf(
" Removed %ld exterior Steiner vertices.\n",
23006 printf(
" Removed %ld exterior input vertices.\n",
23007 unuverts - delvertcount);
23011 cavetetvertlist->restart();
23017 hullsize += (newhullfacearray->objects - hullarray->objects);
23020 for (i = 0; i < tetarray->objects; i++) {
23021 parytet = (triface *) fastlookup(tetarray, i);
23022 tetrahedrondealloc(parytet->tet);
23024 tetarray->restart();
23026 for (i = 0; i < hullarray->objects; i++) {
23027 parytet = (triface *) fastlookup(hullarray, i);
23028 tetrahedrondealloc(parytet->tet);
23030 hullarray->restart();
23032 delete newhullfacearray;
23035 if (b->convex && (tetarray->objects > 0l)) {
23037 int attrnum = numelemattrib - 1;
23039 for (i = 0; i < tetarray->objects; i++) {
23040 parytet = (triface *) fastlookup(tetarray, i);
23041 setelemattribute(parytet->tet, attrnum, -1);
23043 tetarray->restart();
23045 for (i = 0; i < hullarray->objects; i++) {
23046 parytet = (triface *) fastlookup(hullarray, i);
23047 uninfect(*parytet);
23049 hullarray->restart();
23051 if (subfacstack->objects > 0l) {
23052 for (i = 0; i < subfacstack->objects; i++) {
23053 parysh = (face *) fastlookup(subfacstack, i);
23054 suninfect(*parysh);
23056 subfacstack->restart();
23059 if (cavetetvertlist->objects > 0l) {
23060 cavetetvertlist->restart();
23064 if (b->regionattrib) {
23066 printf(
"Spreading region attributes.\n");
23069 int attr, maxattr = 0;
23070 int attrnum = numelemattrib - 1;
23073 int regioncount = 0;
23076 if (in->numberofregions > 0) {
23078 for (i = 0; i < 5 * in->numberofregions; i += 5) {
23079 if (regiontets[i/5].tet != NULL) {
23080 attr = (int) in->regionlist[i + 3];
23081 if (attr > maxattr) {
23084 volume = in->regionlist[i + 4];
23085 tetarray->restart();
23086 infect(regiontets[i/5]);
23087 tetarray->newindex((
void **) &parytet);
23088 *parytet = regiontets[i/5];
23090 for (j = 0; j < tetarray->objects; j++) {
23091 parytet = (triface *) fastlookup(tetarray, j);
23092 tetloop = *parytet;
23093 setelemattribute(tetloop.tet, attrnum, attr);
23094 if (b->varvolume) {
23095 setvolumebound(tetloop.tet, volume);
23097 for (k = 0; k < 4; k++) {
23098 decode(tetloop.tet[k], neightet);
23100 if (!infected(neightet)) {
23102 if (!issubface(neightet)) {
23104 tetarray->newindex((
void **) &parytet);
23105 *parytet = neightet;
23116 attr = maxattr + 1;
23117 tetrahedrons->traversalinit();
23118 tetloop.tet = tetrahedrontraverse();
23119 while (tetloop.tet != (tetrahedron *) NULL) {
23120 if (!infected(tetloop)) {
23122 tetarray->restart();
23124 tetarray->newindex((
void **) &parytet);
23125 *parytet = tetloop;
23127 for (j = 0; j < tetarray->objects; j++) {
23128 parytet = (triface *) fastlookup(tetarray, j);
23129 tetloop = *parytet;
23130 setelemattribute(tetloop.tet, attrnum, attr);
23131 for (k = 0; k < 4; k++) {
23132 decode(tetloop.tet[k], neightet);
23134 if (!infected(neightet)) {
23136 if (!issubface(neightet)) {
23138 tetarray->newindex((
void **) &parytet);
23139 *parytet = neightet;
23147 tetloop.tet = tetrahedrontraverse();
23152 tetrahedrons->traversalinit();
23153 tetloop.tet = tetrahedrontraverse();
23154 while (tetloop.tet != (tetrahedron *) NULL) {
23156 tetloop.tet = tetrahedrontraverse();
23161 if (regioncount > 1) {
23162 printf(
" Found %d subdomains.\n", regioncount);
23164 printf(
" Found %d domain.\n", regioncount);
23169 if (regiontets != NULL) {
23170 delete [] regiontets;
23180 tetrahedrons->traversalinit();
23182 tetloop.tet = alltetrahedrontraverse();
23183 while (tetloop.tet != (tetrahedron *) NULL) {
23184 if ((point) tetloop.tet[7] == dummypoint) {
23185 fsym(tetloop, neightet);
23186 flippush(flipstack, &neightet);
23188 tetloop.tet = alltetrahedrontraverse();
23191 flipconstraints fc;
23193 long sliver_peel_count = lawsonflip3d(&fc);
23195 if (sliver_peel_count > 0l) {
23197 printf(
" Removed %ld hull slivers.\n", sliver_peel_count);
23200 unflipqueue->restart();
23209 int tetgenmesh::search_face(point pi, point pj, point pk, triface &tetloop)
23220 t.ver = t1.ver = 0;
23221 tetrahedrons->traversalinit();
23222 t.tet = tetrahedrontraverse();
23223 while (t.tet != NULL) {
23224 pts = (point *) t.tet;
23226 if (pinfected(pts[4])) pcount++;
23227 if (pinfected(pts[5])) pcount++;
23228 if (pinfected(pts[6])) pcount++;
23229 if (pinfected(pts[7])) pcount++;
23233 for (t.ver = 0; t.ver < 4; t.ver++) {
23235 if (!pinfected(toppo))
break;
23238 for (ii = 0; ii < 3; ii++) {
23239 if (org(t) == pi)
break;
23242 if (dest(t) == pj) {
23249 t.tet = tetrahedrontraverse();
23256 if (t.tet != NULL) {
23264 int tetgenmesh::search_edge(point p0, point p1, triface &tetloop)
23269 tetrahedrons->traversalinit();
23270 t.tet = tetrahedrontraverse();
23271 while (t.tet != NULL) {
23272 for (ii = 0; ii < 6; ii++) {
23273 t.ver = edge2ver[ii];
23274 if (((org(t) == p0) && (dest(t) == p1)) ||
23275 ((org(t) == p1) && (dest(t) == p0))) {
23281 t.tet = tetrahedrontraverse();
23284 tetloop.tet = NULL;
23294 void tetgenmesh::reconstructmesh()
23296 tetrahedron *ver2tetarray;
23297 point *idx2verlist;
23298 triface tetloop, checktet, prevchktet;
23299 triface hulltet, face1, face2;
23301 face subloop, neighsh, nextsh;
23305 REAL ori, attrib, volume;
23306 REAL cosang_tol, cosang;
23308 int eextras, marker = 0;
23314 printf(
"Reconstructing mesh ...\n");
23319 if (!(in->numberoftetrahedronattributes > 0)) {
23320 terminatetetgen(
this, 2);
23328 makeindex2pointmap(idx2verlist);
23330 if (in->firstnumber == 1) {
23331 idx2verlist[0] = dummypoint;
23335 ver2tetarray =
new tetrahedron[in->numberofpoints + 1];
23336 unuverts = in->numberofpoints;
23338 for (i = in->firstnumber; i < in->numberofpoints + in->firstnumber; i++) {
23339 ver2tetarray[i] = NULL;
23343 for (i = 0; i < in->numberoftetrahedra; i++) {
23345 idx = i * in->numberofcorners;
23346 for (j = 0; j < 4; j++) {
23347 p[j] = idx2verlist[in->tetrahedronlist[idx++]];
23348 if (pointtype(p[j]) == UNUSEDVERTEX) {
23349 setpointtype(p[j], VOLVERTEX);
23354 ori = orient3d(p[0], p[1], p[2], p[3]);
23357 q[0] = p[0]; p[0] = p[1]; p[1] = q[0];
23358 }
else if (ori == 0.0) {
23360 printf(
"Warning: Tet #%d is degenerate.\n", i + in->firstnumber);
23364 maketetrahedron(&tetloop);
23365 setvertices(tetloop, p[0], p[1], p[2], p[3]);
23367 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
23368 idx = i * in->numberoftetrahedronattributes;
23369 attrib = in->tetrahedronattributelist[idx + j];
23370 setelemattribute(tetloop.tet, j, attrib);
23374 if (b->varvolume) {
23375 if (in->tetrahedronvolumelist != (REAL *) NULL) {
23376 volume = in->tetrahedronvolumelist[i];
23380 setvolumebound(tetloop.tet, volume);
23383 for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
23384 p[3] = oppo(tetloop);
23386 idx = pointmark(p[3]);
23387 tptr = ver2tetarray[idx];
23389 tetloop.tet[8 + tetloop.ver] = tptr;
23391 ver2tetarray[idx] = encode(tetloop);
23392 decode(tptr, checktet);
23393 if (checktet.tet != NULL) {
23394 p[0] = org(tetloop);
23395 p[1] = dest(tetloop);
23396 p[2] = apex(tetloop);
23397 prevchktet = tetloop;
23399 q[0] = org(checktet);
23400 q[1] = dest(checktet);
23401 q[2] = apex(checktet);
23404 for (j = 0; j < 3; j++) {
23406 esym(checktet, face2);
23407 if (face2.tet[face2.ver & 3] == NULL) {
23409 if (q[k] == p[0]) {
23410 if (q[j] == p[1]) {
23412 esym(tetloop, face1);
23413 bond(face1, face2);
23417 if (q[k] == p[1]) {
23418 if (q[j] == p[2]) {
23420 enext(tetloop, face1);
23422 bond(face1, face2);
23426 if (q[k] == p[2]) {
23427 if (q[j] == p[0]) {
23429 eprev(tetloop, face1);
23431 bond(face1, face2);
23438 enextself(checktet);
23441 tptr = checktet.tet[8 + checktet.ver];
23442 if (bondflag == 3) {
23445 prevchktet.tet[8 + prevchktet.ver] = tptr;
23448 prevchktet = checktet;
23450 decode(tptr, checktet);
23451 }
while (checktet.tet != NULL);
23457 recenttet = tetloop;
23461 hullsize = tetrahedrons->items;
23463 tetrahedrons->traversalinit();
23464 tetloop.tet = tetrahedrontraverse();
23465 while (tetloop.tet != (tetrahedron *) NULL) {
23466 tptr = encode(tetloop);
23467 for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
23468 if (tetloop.tet[tetloop.ver] == NULL) {
23470 maketetrahedron(&hulltet);
23471 p[0] = org(tetloop);
23472 p[1] = dest(tetloop);
23473 p[2] = apex(tetloop);
23474 setvertices(hulltet, p[1], p[0], p[2], dummypoint);
23475 bond(tetloop, hulltet);
23477 for (j = 0; j < 3; j++) {
23478 fsym(hulltet, face2);
23480 if (face2.tet == NULL)
break;
23482 if (apex(face2) == dummypoint)
break;
23485 if (face2.tet != NULL) {
23487 esym(hulltet, face1);
23488 bond(face1, face2);
23490 enextself(hulltet);
23494 setpoint2tet((point) (tetloop.tet[4 + tetloop.ver]), tptr);
23496 tetloop.tet[8 + tetloop.ver] = NULL;
23498 tetloop.tet = tetrahedrontraverse();
23501 hullsize = tetrahedrons->items - hullsize;
23504 if (in->trifacelist != NULL) {
23506 for (i = 0; i < in->numberoftrifaces; i++) {
23508 if (in->trifacemarkerlist != NULL) {
23509 marker = in->trifacemarkerlist[i];
23516 for (j = 0; j < 3; j++) {
23517 p[j] = idx2verlist[in->trifacelist[idx++]];
23523 for (j = 0; j < 3; j++) {
23524 decode(point2tet(p[j]), checktet);
23525 if (checktet.tet == NULL)
break;
23527 if ((j == 3) && getedge(p[0], p[1], &checktet)) {
23528 tetloop = checktet;
23529 q[2] = apex(checktet);
23531 if (apex(tetloop) == p[2]) {
23534 tspivot(tetloop, neighsh);
23535 if (neighsh.sh != NULL) {
23544 fnextself(tetloop);
23545 if (apex(tetloop) == q[2])
break;
23549 if (neighsh.sh == NULL) {
23550 if (b->verbose > 1) {
23551 printf(
"Warning: Searching subface #%d [%d,%d,%d] mark=%d.\n",
23552 i + in->firstnumber, pointmark(p[0]), pointmark(p[1]),
23553 pointmark(p[2]), marker);
23556 if (search_face(p[0], p[1], p[2], tetloop)) {
23563 makeshellface(subfaces, &subloop);
23564 setshvertices(subloop, p[0], p[1], p[2]);
23566 sptr = sencode(subloop);
23567 for (j = 0; j < 3; j++) {
23568 setpointtype(p[j], FACETVERTEX);
23569 setpoint2sh(p[j], sptr);
23571 setshellmark(subloop, marker);
23573 tsbond(tetloop, subloop);
23575 sesymself(subloop);
23576 tsbond(tetloop, subloop);
23578 if (neighsh.sh != NULL) {
23580 setshellmark(neighsh, marker);
23583 printf(
"Warning: Subface #%d [%d,%d,%d] mark=%d is not found.\n",
23584 i + in->firstnumber, pointmark(p[0]), pointmark(p[1]),
23585 pointmark(p[2]), marker);
23596 eextras = in->numberoftetrahedronattributes;
23597 tetrahedrons->traversalinit();
23598 tetloop.tet = tetrahedrontraverse();
23599 while (tetloop.tet != (tetrahedron *) NULL) {
23600 for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
23601 tspivot(tetloop, neighsh);
23602 if (neighsh.sh == NULL) {
23604 fsym(tetloop, checktet);
23605 if (ishulltet(checktet)) {
23612 if (elemattribute(tetloop.tet, eextras - 1) !=
23613 elemattribute(checktet.tet, eextras - 1)) {
23620 makeshellface(subfaces, &subloop);
23621 p[0] = org(tetloop);
23622 p[1] = dest(tetloop);
23623 p[2] = apex(tetloop);
23624 setshvertices(subloop, p[0], p[1], p[2]);
23626 sptr = sencode(subloop);
23627 for (j = 0; j < 3; j++) {
23628 setpointtype(p[j], FACETVERTEX);
23629 setpoint2sh(p[j], sptr);
23631 setshellmark(subloop, -1);
23633 tsbond(tetloop, subloop);
23634 sesymself(subloop);
23635 tsbond(checktet, subloop);
23639 tetloop.tet = tetrahedrontraverse();
23643 subfaces->traversalinit();
23645 subloop.sh = shellfacetraverse(subfaces);
23646 while (subloop.sh != (shellface *) NULL) {
23647 for (i = 0; i < 3; i++) {
23648 spivot(subloop, neighsh);
23649 if (neighsh.sh == NULL) {
23652 stpivot(subloop, tetloop);
23653 q[2] = apex(tetloop);
23656 fnextself(tetloop);
23657 tspivot(tetloop, nextsh);
23658 if (nextsh.sh != NULL) {
23660 if (nextsh.sh != neighsh.sh) {
23662 sbond1(neighsh, nextsh);
23666 if (apex(tetloop) == q[2]) {
23671 senextself(subloop);
23673 subloop.sh = shellfacetraverse(subfaces);
23678 if (in->edgelist != NULL) {
23680 for (i = 0; i < in->numberofedges; i++) {
23682 if (in->edgemarkerlist != NULL) {
23683 marker = in->edgemarkerlist[i];
23691 for (j = 0; j < 2; j++) {
23692 p[j] = idx2verlist[in->edgelist[idx++]];
23695 for (j = 0; j < 2; j++) {
23696 decode(point2tet(p[j]), checktet);
23697 if (checktet.tet == NULL)
break;
23702 if (getedge(p[0], p[1], &checktet)) {
23705 if (b->verbose > 1) {
23706 printf(
"Warning: Searching segment #%d [%d,%d] mark=%d.\n",
23707 i + in->firstnumber, pointmark(p[0]), pointmark(p[1]), marker);
23710 if (search_edge(p[0], p[1], checktet)) {
23715 if (bondflag > 0) {
23717 makeshellface(subsegs, &segloop);
23718 setshvertices(segloop, p[0], p[1], NULL);
23720 sptr = sencode(segloop);
23721 for (j = 0; j < 2; j++) {
23722 setpointtype(p[j], RIDGEVERTEX);
23723 setpoint2sh(p[j], sptr);
23725 setshellmark(segloop, marker);
23727 tetloop = checktet;
23728 q[2] = apex(checktet);
23731 tssbond1(tetloop, segloop);
23732 tspivot(tetloop, subloop);
23733 if (subloop.sh != NULL) {
23734 ssbond1(subloop, segloop);
23735 sbond1(segloop, subloop);
23737 fnextself(tetloop);
23738 if (apex(tetloop) == q[2])
break;
23741 sstbond1(segloop, tetloop);
23744 printf(
"Warning: Segment #%d [%d,%d] is missing.\n",
23745 i + in->firstnumber, pointmark(p[0]), pointmark(p[1]));
23756 cosang_tol = cos(b->facet_separate_ang_tol / 180.0 * PI);
23757 subfaces->traversalinit();
23759 subloop.sh = shellfacetraverse(subfaces);
23760 while (subloop.sh != (shellface *) NULL) {
23761 for (i = 0; i < 3; i++) {
23762 sspivot(subloop, segloop);
23763 if (segloop.sh == NULL) {
23771 spivotself(nextsh);
23772 if (nextsh.sh == subloop.sh)
break;
23776 p[0] = sorg(subloop);
23777 p[1] = sdest(subloop);
23780 spivot(subloop, neighsh);
23781 if (shellmark(subloop) != shellmark(neighsh)) {
23783 p[0] = sorg(subloop);
23784 p[1] = sdest(subloop);
23789 p[0] = sorg(subloop);
23790 p[1] = sdest(subloop);
23791 p[2] = sapex(subloop);
23792 p[3] = sapex(neighsh);
23793 facenormal(p[0], p[1], p[2], n1, 1, NULL);
23794 facenormal(p[0], p[1], p[3], n2, 1, NULL);
23795 cosang = dot(n1, n2) / (sqrt(dot(n1, n1)) * sqrt(dot(n2, n2)));
23797 if (cosang > 1.0) cosang = 1.0;
23798 else if (cosang < -1.0) cosang = -1.0;
23799 if (cosang > cosang_tol) {
23807 makeshellface(subsegs, &segloop);
23808 setshvertices(segloop, p[0], p[1], NULL);
23810 sptr = sencode(segloop);
23811 for (j = 0; j < 2; j++) {
23812 setpointtype(p[j], RIDGEVERTEX);
23813 setpoint2sh(p[j], sptr);
23815 setshellmark(segloop, -1);
23817 stpivot(subloop, tetloop);
23818 q[2] = apex(tetloop);
23820 tssbond1(tetloop, segloop);
23821 tspivot(tetloop, neighsh);
23822 if (neighsh.sh != NULL) {
23823 ssbond1(neighsh, segloop);
23825 fnextself(tetloop);
23826 if (apex(tetloop) == q[2])
break;
23829 sstbond1(segloop, tetloop);
23830 sbond1(segloop, subloop);
23833 senextself(subloop);
23835 subloop.sh = shellfacetraverse(subfaces);
23839 insegments = subsegs->items;
23841 if (!b->nobisect || checkconstraints) {
23846 face* segperverlist;
23848 face parentseg, nextseg;
23850 REAL area, len, l1, l2;
23853 makepoint2submap(subsegs, idx2seglist, segperverlist);
23855 points->traversalinit();
23856 point ptloop = pointtraverse();
23857 while (ptloop != NULL) {
23858 vt = pointtype(ptloop);
23859 if (vt == VOLVERTEX) {
23860 setpointtype(ptloop, FREEVOLVERTEX);
23862 }
else if (vt == FACETVERTEX) {
23863 setpointtype(ptloop, FREEFACETVERTEX);
23865 }
else if (vt == RIDGEVERTEX) {
23866 idx = pointmark(ptloop) - in->firstnumber;
23867 if ((idx2seglist[idx + 1] - idx2seglist[idx]) == 2) {
23868 i = idx2seglist[idx];
23869 parentseg = segperverlist[i];
23870 nextseg = segperverlist[i + 1];
23871 sesymself(nextseg);
23872 p[0] = sorg(nextseg);
23873 p[1] = sdest(parentseg);
23875 len = distance(p[0], p[1]);
23876 l1 = distance(p[0], ptloop);
23877 l2 = distance(ptloop, p[1]);
23878 if (((l1 + l2 - len) / len) < b->epsilon) {
23880 setpointtype(ptloop, FREESEGVERTEX);
23882 senextself(nextseg);
23883 senext2self(parentseg);
23884 sbond(nextseg, parentseg);
23889 ptloop = pointtraverse();
23893 if (b->quality && (in->facetconstraintlist != (REAL *) NULL)) {
23895 for (i = 0; i < in->numberoffacetconstraints; i++) {
23896 fmarker = (int) in->facetconstraintlist[i * 2];
23897 area = in->facetconstraintlist[i * 2 + 1];
23898 subfaces->traversalinit();
23899 subloop.sh = shellfacetraverse(subfaces);
23900 while (subloop.sh != NULL) {
23901 if (shellmark(subloop) == fmarker) {
23902 setareabound(subloop, area);
23904 subloop.sh = shellfacetraverse(subfaces);
23910 if (b->quality && (in->segmentconstraintlist != (REAL *) NULL)) {
23913 for (i = 0; i < in->numberofsegmentconstraints; i++) {
23914 e1 = (int) in->segmentconstraintlist[i * 3];
23915 e2 = (
int) in->segmentconstraintlist[i * 3 + 1];
23916 len = in->segmentconstraintlist[i * 3 + 2];
23918 idx = e1 - in->firstnumber;
23919 for (j = idx2seglist[idx]; j < idx2seglist[idx + 1]; j++) {
23920 parentseg = segperverlist[j];
23921 if (pointmark(sdest(parentseg)) == e2) {
23922 setareabound(parentseg, len);
23929 delete [] idx2seglist;
23930 delete [] segperverlist;
23935 checksubsegflag = 1;
23936 checksubfaceflag = 1;
23938 delete [] idx2verlist;
23939 delete [] ver2tetarray;
23954 int tetgenmesh::scoutpoint(point searchpt, triface *searchtet,
int randflag)
23956 point pa, pb, pc, pd;
23957 enum locateresult loc = OUTSIDE;
23958 REAL vol, ori1, ori2 = 0, ori3 = 0, ori4 = 0;
23964 randomsample(searchpt, searchtet);
23966 if (searchtet->tet == NULL) {
23967 *searchtet = recenttet;
23970 loc = locate(searchpt, searchtet);
23972 if (loc == OUTSIDE) {
23979 pa = org(*searchtet);
23980 pb = dest(*searchtet);
23981 pc = apex(*searchtet);
23982 vol = triarea(pa, pb, pc);
23983 ori1 = orient3dfast(pa, pb, pc, searchpt);
23984 if (fabs(ori1 / vol) < b->epsilon) {
23986 fsymself(*searchtet);
23990 if (loc != OUTSIDE) {
23992 pa = org(*searchtet);
23993 pb = dest(*searchtet);
23994 pc = apex(*searchtet);
23995 pd = oppo(*searchtet);
23996 vol = orient3dfast(pa, pb, pc, pd);
23997 ori1 = orient3dfast(pa, pb, pc, searchpt);
23998 ori2 = orient3dfast(pb, pa, pd, searchpt);
23999 ori3 = orient3dfast(pc, pb, pd, searchpt);
24000 ori4 = orient3dfast(pa, pc, pd, searchpt);
24001 if (fabs(ori1 / vol) < b->epsilon) ori1 = 0;
24002 if (fabs(ori2 / vol) < b->epsilon) ori2 = 0;
24003 if (fabs(ori3 / vol) < b->epsilon) ori3 = 0;
24004 if (fabs(ori4 / vol) < b->epsilon) ori4 = 0;
24007 tetrahedrons->traversalinit();
24008 searchtet->tet = tetrahedrontraverse();
24009 while (searchtet->tet != NULL) {
24010 pa = org(*searchtet);
24011 pb = dest(*searchtet);
24012 pc = apex(*searchtet);
24013 pd = oppo(*searchtet);
24015 vol = orient3dfast(pa, pb, pc, pd);
24017 ori1 = orient3dfast(pa, pb, pc, searchpt);
24018 if (fabs(ori1 / vol) < b->epsilon) ori1 = 0;
24020 ori2 = orient3dfast(pb, pa, pd, searchpt);
24021 if (fabs(ori2 / vol) < b->epsilon) ori2 = 0;
24023 ori3 = orient3dfast(pc, pb, pd, searchpt);
24024 if (fabs(ori3 / vol) < b->epsilon) ori3 = 0;
24026 ori4 = orient3dfast(pa, pc, pd, searchpt);
24027 if (fabs(ori4 / vol) < b->epsilon) ori4 = 0;
24037 searchtet->tet = tetrahedrontraverse();
24042 if (searchtet->tet != NULL) {
24047 enextself(*searchtet);
24059 eprevself(*searchtet);
24062 enextself(*searchtet);
24067 eprevself(*searchtet);
24076 esymself(*searchtet);
24078 eprevself(*searchtet);
24086 enextself(*searchtet);
24094 enextself(*searchtet);
24095 esymself(*searchtet);
24097 eprevself(*searchtet);
24104 eprevself(*searchtet);
24105 esymself(*searchtet);
24108 loc = INTETRAHEDRON;
24129 REAL tetgenmesh::getpointmeshsize(point searchpt, triface *searchtet,
int iloc)
24131 point *pts, pa, pb, pc;
24132 REAL volume, vol[4], wei[4];
24138 if (iloc == (
int) INTETRAHEDRON) {
24139 pts = (point *) &(searchtet->tet[4]);
24141 if ((pts[0][pointmtrindex] > 0) && (pts[1][pointmtrindex] > 0) &&
24142 (pts[2][pointmtrindex] > 0) && (pts[3][pointmtrindex] > 0)) {
24144 volume = orient3dfast(pts[0], pts[1], pts[2], pts[3]);
24145 vol[0] = orient3dfast(searchpt, pts[1], pts[2], pts[3]);
24146 vol[1] = orient3dfast(pts[0], searchpt, pts[2], pts[3]);
24147 vol[2] = orient3dfast(pts[0], pts[1], searchpt, pts[3]);
24148 vol[3] = orient3dfast(pts[0], pts[1], pts[2], searchpt);
24149 for (i = 0; i < 4; i++) {
24150 wei[i] = fabs(vol[i] / volume);
24151 size += (wei[i] * pts[i][pointmtrindex]);
24154 }
else if (iloc == (
int) ONFACE) {
24155 pa = org(*searchtet);
24156 pb = dest(*searchtet);
24157 pc = apex(*searchtet);
24158 if ((pa[pointmtrindex] > 0) && (pb[pointmtrindex] > 0) &&
24159 (pc[pointmtrindex] > 0)) {
24160 volume = triarea(pa, pb, pc);
24161 vol[0] = triarea(searchpt, pb, pc);
24162 vol[1] = triarea(pa, searchpt, pc);
24163 vol[2] = triarea(pa, pb, searchpt);
24164 size = (vol[0] / volume) * pa[pointmtrindex]
24165 + (vol[1] / volume) * pb[pointmtrindex]
24166 + (vol[2] / volume) * pc[pointmtrindex];
24168 }
else if (iloc == (
int) ONEDGE) {
24169 pa = org(*searchtet);
24170 pb = dest(*searchtet);
24171 if ((pa[pointmtrindex] > 0) && (pb[pointmtrindex] > 0)) {
24172 volume = distance(pa, pb);
24173 vol[0] = distance(searchpt, pb);
24174 vol[1] = distance(pa, searchpt);
24175 size = (vol[0] / volume) * pa[pointmtrindex]
24176 + (vol[1] / volume) * pb[pointmtrindex];
24178 }
else if (iloc == (
int) ONVERTEX) {
24179 pa = org(*searchtet);
24180 if (pa[pointmtrindex] > 0) {
24181 size = pa[pointmtrindex];
24195 void tetgenmesh::interpolatemeshsize()
24199 REAL minval = 0.0, maxval = 0.0;
24204 printf(
"Interpolating mesh size ...\n");
24207 long bak_nonregularcount = nonregularcount;
24208 nonregularcount = 0l;
24209 long baksmaples = bgm->samples;
24214 points->traversalinit();
24215 ploop = pointtraverse();
24216 while (ploop != NULL) {
24218 searchtet.tet = NULL;
24219 iloc = bgm->scoutpoint(ploop, &searchtet, 1);
24220 if (iloc != (
int) OUTSIDE) {
24222 ploop[pointmtrindex] = bgm->getpointmeshsize(ploop, &searchtet, iloc);
24223 setpoint2bgmtet(ploop, bgm->encode(searchtet));
24226 minval = maxval = ploop[pointmtrindex];
24228 if (ploop[pointmtrindex] < minval) {
24229 minval = ploop[pointmtrindex];
24231 if (ploop[pointmtrindex] > maxval) {
24232 maxval = ploop[pointmtrindex];
24238 printf(
"Warnning: Failed to locate point %d in source mesh.\n",
24242 ploop = pointtraverse();
24246 printf(
" Interoplated %d points.\n", count);
24247 if (nonregularcount > 0l) {
24248 printf(
" Performed %ld brute-force searches.\n", nonregularcount);
24250 printf(
" Size rangle [%.17g, %.17g].\n", minval, maxval);
24253 bgm->samples = baksmaples;
24254 nonregularcount = bak_nonregularcount;
24266 void tetgenmesh::insertconstrainedpoints(point *insertarray,
int arylen,
24269 triface searchtet, spintet;
24272 insertvertexflags ivf;
24273 flipconstraints fc;
24279 printf(
" Inserting %d constrained points\n", arylen);
24284 printf(
" Using the input order.\n");
24288 printf(
" Permuting vertices.\n");
24293 for (i = 0; i < arylen; i++) {
24294 randindex = rand() % (i + 1);
24295 swappoint = insertarray[i];
24296 insertarray[i] = insertarray[randindex];
24297 insertarray[randindex] = swappoint;
24299 if (b->brio_hilbert) {
24301 printf(
" Sorting vertices.\n");
24303 hilbert_init(in->mesh_dim);
24305 brio_multiscale_sort(insertarray, arylen, b->brio_threshold,
24306 b->brio_ratio, &ngroup);
24312 long bak_nonregularcount = nonregularcount;
24313 nonregularcount = 0l;
24314 long baksmaples = samples;
24317 long bak_seg_count = st_segref_count;
24318 long bak_fac_count = st_facref_count;
24319 long bak_vol_count = st_volref_count;
24334 ivf.rejflag = rejflag;
24335 ivf.chkencflag = 0;
24336 ivf.sloc = (int) INSTAR;
24338 ivf.splitbdflag = 1;
24339 ivf.respectbdflag = 1;
24340 ivf.assignmeshsize = b->metric;
24342 encseglist =
new arraypool(
sizeof(face), 8);
24343 encshlist =
new arraypool(
sizeof(badface), 8);
24346 for (i = 0; i < arylen; i++) {
24349 searchtet.tet = NULL;
24350 ivf.iloc = scoutpoint(insertarray[i], &searchtet, randflag);
24353 setpointtype(insertarray[i], FREEVOLVERTEX);
24355 splitseg.sh = NULL;
24356 if (ivf.iloc == (
int) ONEDGE) {
24357 if (issubseg(searchtet)) {
24358 tsspivot1(searchtet, splitseg);
24359 setpointtype(insertarray[i], FREESEGVERTEX);
24363 spintet = searchtet;
24365 if (issubface(spintet)) {
24366 tspivot(spintet, splitsh);
24367 setpointtype(insertarray[i], FREEFACETVERTEX);
24371 fnextself(spintet);
24372 if (spintet.tet == searchtet.tet)
break;
24375 }
else if (ivf.iloc == (
int) ONFACE) {
24376 if (issubface(searchtet)) {
24377 tspivot(searchtet, splitsh);
24378 setpointtype(insertarray[i], FREEFACETVERTEX);
24384 if (insertpoint(insertarray[i], &searchtet, &splitsh, &splitseg, &ivf)) {
24385 if (flipstack != NULL) {
24389 unflipqueue->restart();
24392 if (pointtype(insertarray[i]) == FREESEGVERTEX) {
24394 }
else if (pointtype(insertarray[i]) == FREEFACETVERTEX) {
24402 setpointtype(insertarray[i], UNUSEDVERTEX);
24404 encseglist->restart();
24405 encshlist->restart();
24413 printf(
" Inserted %ld (%ld, %ld, %ld) vertices.\n",
24414 st_segref_count + st_facref_count + st_volref_count -
24415 (bak_seg_count + bak_fac_count + bak_vol_count),
24416 st_segref_count - bak_seg_count, st_facref_count - bak_fac_count,
24417 st_volref_count - bak_vol_count);
24418 if (nonregularcount > 0l) {
24419 printf(
" Performed %ld brute-force searches.\n", nonregularcount);
24423 nonregularcount = bak_nonregularcount;
24424 samples = baksmaples;
24427 void tetgenmesh::insertconstrainedpoints(
tetgenio *addio)
24429 point *insertarray, newpt;
24431 int index, attribindex, mtrindex;
24435 printf(
"Inserting constrained points ...\n");
24438 insertarray =
new point[addio->numberofpoints];
24444 for (i = 0; i < addio->numberofpoints; i++) {
24445 x = addio->pointlist[index++];
24446 y = addio->pointlist[index++];
24447 z = addio->pointlist[index++];
24449 if ((x < xmin) || (x > xmax) || (y < ymin) || (y > ymax) ||
24450 (z < zmin) || (z > zmax)) {
24452 printf(
"Warning: Point #%d lies outside the bounding box. Ignored\n",
24453 i + in->firstnumber);
24457 makepoint(&newpt, UNUSEDVERTEX);
24462 for (j = 0; j < addio->numberofpointattributes; j++) {
24463 newpt[3 + j] = addio->pointattributelist[attribindex++];
24466 for (j = 0; j < addio->numberofpointmtrs; j++) {
24467 newpt[pointmtrindex + j] = addio->pointmtrlist[mtrindex++];
24470 if (addio->numberofpointattributes > 0) {
24477 if (w < fabs(y)) w = fabs(y);
24478 if (w < fabs(z)) w = fabs(z);
24480 if (b->weighted_param == 0) {
24481 newpt[3] = x * x + y * y + z * z - w;
24486 insertarray[arylen] = newpt;
24496 insertconstrainedpoints(insertarray, arylen, rejflag);
24498 delete [] insertarray;
24507 void tetgenmesh::collectremovepoints(arraypool *remptlist)
24509 point ptloop, *parypt;
24517 points->traversalinit();
24518 ptloop = pointtraverse();
24519 while (ptloop != NULL) {
24521 vt = pointtype(ptloop);
24522 if ((vt == RIDGEVERTEX) || (vt == ACUTEVERTEX) || (vt == FACETVERTEX) ||
24523 (vt == FREEFACETVERTEX) || (vt == FREESEGVERTEX) || (vt == UNUSEDVERTEX)) {
24524 ptloop = pointtraverse();
24527 if (ptloop[pointmtrindex] > 0) {
24529 getvertexstar(1, ptloop, cavetetlist, cavetetvertlist, NULL);
24530 parypt = (point *) fastlookup(cavetetvertlist, 0);
24531 smlen = distance(ptloop, *parypt);
24532 for (i = 1; i < cavetetvertlist->objects; i++) {
24533 parypt = (point *) fastlookup(cavetetvertlist, i);
24534 len = distance(ptloop, *parypt);
24539 cavetetvertlist->restart();
24540 cavetetlist->restart();
24541 if (smlen < ptloop[pointmtrindex]) {
24543 remptlist->newindex((
void **) &parypt);
24547 ptloop = pointtraverse();
24549 if (b->verbose > 1) {
24550 printf(
" Coarsen %ld oversized points.\n", remptlist->objects);
24555 if (in->pointmarkerlist != NULL) {
24556 long bak_count = remptlist->objects;
24557 points->traversalinit();
24558 ptloop = pointtraverse();
24560 while (ptloop != NULL) {
24561 if (index < in->numberofpoints) {
24562 if (in->pointmarkerlist[index] == -1) {
24564 remptlist->newindex((
void **) &parypt);
24572 ptloop = pointtraverse();
24574 if (b->verbose > 1) {
24575 printf(
" Coarsen %ld marked points.\n", remptlist->objects - bak_count);
24579 if (b->coarsen_param > 0) {
24581 if (b->verbose > 1) {
24582 printf(
" Coarsen %g percent of interior points.\n",
24583 b->coarsen_percent * 100.0);
24585 arraypool *intptlist =
new arraypool(
sizeof(point *), 10);
24587 points->traversalinit();
24588 ptloop = pointtraverse();
24589 while (ptloop != NULL) {
24590 vt = pointtype(ptloop);
24591 if ((vt == VOLVERTEX) || (vt == FREEVOLVERTEX) ||
24592 (vt == FREEFACETVERTEX) || (vt == FREESEGVERTEX)) {
24593 intptlist->newindex((
void **) &parypt);
24596 ptloop = pointtraverse();
24598 if (intptlist->objects > 0l) {
24600 point *parypt_i, swappt;
24602 srand(intptlist->objects);
24603 for (i = 0; i < intptlist->objects; i++) {
24604 randindex = rand() % (i + 1);
24605 parypt_i = (point *) fastlookup(intptlist, i);
24606 parypt = (point *) fastlookup(intptlist, randindex);
24608 swappt = *parypt_i;
24609 *parypt_i = *parypt;
24612 int remcount = (int) ((REAL) intptlist->objects * b->coarsen_percent);
24614 for (i = 0; i < remcount; i++) {
24615 parypt_i = (point *) fastlookup(intptlist, i);
24616 if (!pinfected(*parypt_i)) {
24617 pinfected(*parypt_i);
24618 remptlist->newindex((
void **) &parypt);
24619 *parypt = *parypt_i;
24627 for (
int i = 0; i < remptlist->objects; i++) {
24628 parypt = (point *) fastlookup(remptlist, i);
24629 puninfect(*parypt);
24633 void tetgenmesh::meshcoarsening()
24635 arraypool *remptlist;
24638 printf(
"Mesh coarsening ...\n");
24642 remptlist =
new arraypool(
sizeof(point *), 10);
24643 collectremovepoints(remptlist);
24645 if (remptlist->objects == 0l) {
24651 if (remptlist->objects > 0l) {
24652 printf(
" Removing %ld points...\n", remptlist->objects);
24656 point *parypt, *plastpt;
24657 long ms = remptlist->objects;
24659 int bak_fliplinklevel = b->fliplinklevel;
24660 b->fliplinklevel = -1;
24661 autofliplinklevel = 1;
24666 if (b->verbose > 1) {
24667 printf(
" Removing points [%s level = %2d] #: %ld.\n",
24668 (b->fliplinklevel > 0) ?
"fixed" :
"auto",
24669 (b->fliplinklevel > 0) ? b->fliplinklevel : autofliplinklevel,
24670 remptlist->objects);
24674 for (i = 0; i < remptlist->objects; i++) {
24675 parypt = (point *) fastlookup(remptlist, i);
24676 if (removevertexbyflips(*parypt)) {
24678 plastpt = (point *) fastlookup(remptlist, remptlist->objects - 1);
24679 *parypt = *plastpt;
24680 remptlist->objects--;
24685 if (remptlist->objects > 0l) {
24686 if (b->fliplinklevel >= 0) {
24689 if (remptlist->objects == ms) {
24693 b->fliplinklevel = 100000;
24696 ms = remptlist->objects;
24701 autofliplinklevel+=b->fliplinklevelinc;
24708 if (remptlist->objects > 0l) {
24710 printf(
" %ld points are not removed !\n", remptlist->objects);
24714 b->fliplinklevel = bak_fliplinklevel;
24735 void tetgenmesh::makefacetverticesmap()
24737 arraypool *facetvertexlist, *vertlist, **paryvertlist;
24738 face subloop, neighsh, *parysh, *parysh1;
24739 point pa, *ppt, *parypt;
24741 int facetindex, totalvertices;
24745 printf(
" Creating the facet vertices map.\n");
24748 facetvertexlist =
new arraypool(
sizeof(arraypool *), 10);
24749 facetindex = totalvertices = 0;
24751 subfaces->traversalinit();
24752 subloop.sh = shellfacetraverse(subfaces);
24753 while (subloop.sh != NULL) {
24754 if (!sinfected(subloop)) {
24756 vertlist =
new arraypool(
sizeof(point *), 8);
24757 ppt = (point *) &(subloop.sh[3]);
24758 for (k = 0; k < 3; k++) {
24759 vt = pointtype(ppt[k]);
24760 if ((vt != FREESEGVERTEX) && (vt != FREEFACETVERTEX)) {
24762 vertlist->newindex((
void **) &parypt);
24767 caveshlist->newindex((
void **) &parysh);
24769 for (i = 0; i < caveshlist->objects; i++) {
24770 parysh = (face *) fastlookup(caveshlist, i);
24771 setfacetindex(*parysh, facetindex);
24772 for (j = 0; j < 3; j++) {
24773 if (!isshsubseg(*parysh)) {
24774 spivot(*parysh, neighsh);
24775 if (!sinfected(neighsh)) {
24776 pa = sapex(neighsh);
24777 if (!pinfected(pa)) {
24778 vt = pointtype(pa);
24779 if ((vt != FREESEGVERTEX) && (vt != FREEFACETVERTEX)) {
24781 vertlist->newindex((
void **) &parypt);
24786 caveshlist->newindex((
void **) &parysh1);
24787 *parysh1 = neighsh;
24790 senextself(*parysh);
24793 totalvertices += (int) vertlist->objects;
24795 for (k = 0; k < vertlist->objects; k++) {
24796 parypt = (point *) fastlookup(vertlist, k);
24797 puninfect(*parypt);
24799 caveshlist->restart();
24801 facetvertexlist->newindex((
void **) &paryvertlist);
24802 *paryvertlist = vertlist;
24805 subloop.sh = shellfacetraverse(subfaces);
24809 subfaces->traversalinit();
24810 subloop.sh = shellfacetraverse(subfaces);
24811 while (subloop.sh != NULL) {
24812 suninfect(subloop);
24813 subloop.sh = shellfacetraverse(subfaces);
24817 printf(
" Found %ld facets.\n", facetvertexlist->objects);
24820 idx2facetlist =
new int[facetindex + 1];
24821 facetverticeslist =
new point[totalvertices];
24823 totalworkmemory += ((facetindex + 1) *
sizeof(
int) +
24824 totalvertices *
sizeof(point *));
24826 idx2facetlist[0] = 0;
24827 for (i = 0, k = 0; i < facetindex; i++) {
24828 paryvertlist = (arraypool **) fastlookup(facetvertexlist, i);
24829 vertlist = *paryvertlist;
24830 idx2facetlist[i + 1] = (idx2facetlist[i] + (int) vertlist->objects);
24831 for (j = 0; j < vertlist->objects; j++) {
24832 parypt = (point *) fastlookup(vertlist, j);
24833 facetverticeslist[k] = *parypt;
24839 for (i = 0; i < facetvertexlist->objects; i++) {
24840 paryvertlist = (arraypool **) fastlookup(facetvertexlist, i);
24841 vertlist = *paryvertlist;
24844 delete facetvertexlist;
24854 int tetgenmesh::segsegadjacent(face *seg1, face *seg2)
24856 int segidx1 = getfacetindex(*seg1);
24857 int segidx2 = getfacetindex(*seg2);
24859 if (segidx1 == segidx2)
return 0;
24861 point pa1 = segmentendpointslist[segidx1 * 2];
24862 point pb1 = segmentendpointslist[segidx1 * 2 + 1];
24863 point pa2 = segmentendpointslist[segidx2 * 2];
24864 point pb2 = segmentendpointslist[segidx2 * 2 + 1];
24866 if ((pa1 == pa2) || (pa1 == pb2) || (pb1 == pa2) || (pb1 == pb2)) {
24872 int tetgenmesh::segfacetadjacent(face *subseg, face *subsh)
24874 int segidx = getfacetindex(*subseg);
24875 point pa = segmentendpointslist[segidx * 2];
24876 point pb = segmentendpointslist[segidx * 2 + 1];
24881 int fidx = getfacetindex(*subsh);
24884 for (i = idx2facetlist[fidx]; i < idx2facetlist[fidx+1]; i++) {
24885 if (pinfected(facetverticeslist[i])) count++;
24894 int tetgenmesh::facetfacetadjacent(face *subsh1, face *subsh2)
24898 int fidx1 = getfacetindex(*subsh1);
24899 int fidx2 = getfacetindex(*subsh2);
24901 if (fidx1 == fidx2)
return 0;
24903 for (i = idx2facetlist[fidx1]; i < idx2facetlist[fidx1+1]; i++) {
24904 pinfect(facetverticeslist[i]);
24907 for (i = idx2facetlist[fidx2]; i < idx2facetlist[fidx2+1]; i++) {
24908 if (pinfected(facetverticeslist[i])) count++;
24912 for (i = idx2facetlist[fidx1]; i < idx2facetlist[fidx1+1]; i++) {
24913 puninfect(facetverticeslist[i]);
24929 void tetgenmesh::save_segmentpoint_insradius(point segpt,point parentpt,REAL r)
24932 if (pointtype(parentpt) == FREESEGVERTEX) {
24933 face parentseg1, parentseg2;
24934 sdecode(point2sh(segpt), parentseg1);
24935 sdecode(point2sh(parentpt), parentseg2);
24936 if (segsegadjacent(&parentseg1, &parentseg2)) {
24937 rp = getpointinsradius(parentpt);
24943 }
else if (pointtype(parentpt) == FREEFACETVERTEX) {
24944 face parentseg, parentsh;
24945 sdecode(point2sh(segpt), parentseg);
24946 sdecode(point2sh(parentpt), parentsh);
24947 if (segfacetadjacent(&parentseg, &parentsh)) {
24948 rp = getpointinsradius(parentpt);
24949 if ((sqrt(2.0) * rv) < rp) {
24951 rv = rp / sqrt(2.0);
24955 setpointinsradius(segpt, rv);
24958 void tetgenmesh::save_facetpoint_insradius(point facpt,point parentpt,REAL r)
24961 if (pointtype(parentpt) == FREESEGVERTEX) {
24962 face parentseg, parentsh;
24963 sdecode(point2sh(parentpt), parentseg);
24964 sdecode(point2sh(facpt), parentsh);
24965 if (segfacetadjacent(&parentseg, &parentsh)) {
24966 rp = getpointinsradius(parentpt);
24967 if (rv < (sqrt(2.0) * rp)) {
24968 rv = sqrt(2.0) * rp;
24971 }
else if (pointtype(parentpt) == FREEFACETVERTEX) {
24972 face parentsh1, parentsh2;
24973 sdecode(point2sh(parentpt), parentsh1);
24974 sdecode(point2sh(facpt), parentsh2);
24975 if (facetfacetadjacent(&parentsh1, &parentsh2)) {
24976 rp = getpointinsradius(parentpt);
24982 setpointinsradius(facpt, rv);
24991 void tetgenmesh::enqueuesubface(memorypool *pool, face *chkface)
24993 if (!smarktest2ed(*chkface)) {
24994 smarktest2(*chkface);
24995 face *queface = (face *) pool->alloc();
24996 *queface = *chkface;
25006 void tetgenmesh::enqueuetetrahedron(triface *chktet)
25008 if (!marktest2ed(*chktet)) {
25009 marktest2(*chktet);
25010 triface *quetet = (triface *) badtetrahedrons->alloc();
25021 int tetgenmesh::checkseg4encroach(point pa, point pb, point checkpt)
25026 v1[0] = pa[0] - checkpt[0];
25027 v1[1] = pa[1] - checkpt[1];
25028 v1[2] = pa[2] - checkpt[2];
25029 v2[0] = pb[0] - checkpt[0];
25030 v2[1] = pb[1] - checkpt[1];
25031 v2[2] = pb[2] - checkpt[2];
25033 if (dot(v1, v2) < 0) {
25036 if ((pa[pointmtrindex] > 0) && (pb[pointmtrindex] > 0)) {
25038 REAL prjpt[3], u, v, t;
25039 projpt2edge(checkpt, pa, pb, prjpt);
25041 u = distance(pa, pb);
25042 v = distance(pa, prjpt);
25045 u = pa[pointmtrindex] + t * (pb[pointmtrindex] - pa[pointmtrindex]);
25046 v = distance(checkpt, prjpt);
25076 int tetgenmesh::checkseg4split(face *chkseg, point& encpt,
int& qflag)
25078 REAL ccent[3], len, r;
25081 point forg = sorg(*chkseg);
25082 point fdest = sdest(*chkseg);
25088 len = distance(forg, fdest);
25090 for (i = 0; i < 3; i++) {
25091 ccent[i] = 0.5 * (forg[i] + fdest[i]);
25095 if (checkconstraints && (areabound(*chkseg) > 0.0)) {
25096 if (len > areabound(*chkseg)) {
25102 if (b->fixedvolume) {
25103 if ((len * len * len) > b->maxvolume) {
25111 if (((forg[pointmtrindex] > 0) && (r > forg[pointmtrindex])) ||
25112 ((fdest[pointmtrindex]) > 0 && (r > fdest[pointmtrindex]))) {
25122 triface searchtet, spintet;
25124 REAL d, diff, smdist = 0;
25127 sstpivot1(*chkseg, searchtet);
25128 spintet = searchtet;
25130 eapex = apex(spintet);
25131 if (eapex != dummypoint) {
25132 d = distance(ccent, eapex);
25134 if (fabs(diff) / r < b->epsilon) diff = 0.0;
25137 if (useinsertradius) {
25138 if (encpt == NULL) {
25154 fnextself(spintet);
25155 if (spintet.tet == searchtet.tet)
break;
25158 if (encpt != NULL) {
25177 int tetgenmesh::splitsegment(face *splitseg, point encpt, REAL rrp,
25178 point encpt1, point encpt2,
int qflag,
25182 if (!qflag && smarktest3ed(*splitseg)) {
25189 if (checkconstraints) {
25191 if (areabound(*splitseg) == 0) {
25194 face parentsh, spinsh;
25196 spivot(*splitseg, parentsh);
25197 if (parentsh.sh == NULL) {
25202 if (areabound(spinsh) == 0)
break;
25203 spivotself(spinsh);
25204 if (spinsh.sh == parentsh.sh)
break;
25205 if (spinsh.sh == NULL)
break;
25207 if ((!spinsh.sh) || (areabound(spinsh) == 0)) {
25220 insertvertexflags ivf;
25222 makepoint(&newpt, FREESEGVERTEX);
25223 getsteinerptonsegment(splitseg, encpt, newpt);
25225 if (!qflag && !b->cdtrefine) {
25228 spivot(*splitseg, parentsh);
25229 if (parentsh.sh != NULL) {
25230 face spinsh, neighsh;
25234 for (
int i = 0; i < 2; i++) {
25236 senext(spinsh, neighsh);
25238 senext2(spinsh, neighsh);
25240 if (isshsubseg(neighsh)) {
25241 sspivot(neighsh, neighseg);
25242 if (checkseg4encroach(sorg(neighseg), sdest(neighseg), newpt)) {
25243 pointdealloc(newpt);
25248 spivotself(spinsh);
25249 if (spinsh.sh == NULL)
break;
25250 if (spinsh.sh == parentsh.sh)
break;
25256 sstpivot1(*splitseg, searchtet);
25257 ivf.iloc = (int) ONEDGE;
25265 ivf.chkencflag = chkencflag;
25266 ivf.sloc = (int) INSTAR;
25268 ivf.splitbdflag = 1;
25269 ivf.respectbdflag = 1;
25270 ivf.assignmeshsize = b->metric;
25271 ivf.smlenflag = useinsertradius;
25274 if (insertpoint(newpt, &searchtet, &searchsh, splitseg, &ivf)) {
25276 if (steinerleft > 0) steinerleft--;
25277 if (useinsertradius) {
25278 save_segmentpoint_insradius(newpt, ivf.parentpt, ivf.smlen);
25280 if (flipstack != NULL) {
25281 flipconstraints fc;
25282 fc.chkencflag = chkencflag;
25285 unflipqueue->restart();
25290 if (ivf.iloc == (
int) NEARVERTEX) {
25291 terminatetetgen(
this, 2);
25293 pointdealloc(newpt);
25295 smarktest3(*splitseg);
25306 void tetgenmesh::repairencsegs(
int chkencflag)
25309 point encpt = NULL;
25314 while ((badsubsegs->items > 0) && (steinerleft != 0)) {
25315 badsubsegs->traversalinit();
25316 bface = (face *) badsubsegs->traverse();
25317 while ((bface != NULL) && (steinerleft != 0)) {
25319 if (bface->shver >= 0) {
25321 if ((bface->sh != NULL) && (bface->sh[3] != NULL)) {
25323 if (smarktest2ed(*bface)) {
25324 sunmarktest2(*bface);
25325 if (checkseg4split(bface, encpt, qflag)) {
25326 splitsegment(bface, encpt, 0, NULL, NULL, qflag, chkencflag);
25332 badsubsegs->dealloc((
void *) bface);
25334 bface = (face *) badsubsegs->traverse();
25338 if (badsubsegs->items > 0) {
25340 printf(
"The desired number of Steiner points is reached.\n");
25342 badsubsegs->traversalinit();
25343 bface = (face *) badsubsegs->traverse();
25344 while (bface != NULL) {
25346 if (bface->shver >= 0) {
25347 if ((bface->sh != NULL) && (bface->sh[3] != NULL)) {
25348 if (smarktest2ed(*bface)) {
25349 sunmarktest2(*bface);
25353 bface = (face *) badsubsegs->traverse();
25355 badsubsegs->restart();
25365 int tetgenmesh::checkfac4encroach(point pa, point pb, point pc, point checkpt,
25366 REAL* cent, REAL* r)
25369 int encroached = 0;
25371 circumsphere(pa, pb, pc, NULL, cent, &rd);
25373 terminatetetgen(
this, 2);
25376 if (b->use_equatorial_lens) {
25377 REAL normal[3], fcenter[3];
25378 REAL xta, yta, zta;
25381 fcenter[0] = cent[0] - pc[0];
25382 fcenter[1] = cent[1] - pc[1];
25383 fcenter[2] = cent[2] - pc[2];
25386 facenormal(pa, pb, pc, normal, 1, NULL);
25387 multiplier = 0.985 * sqrt((fcenter[0]*fcenter[0] + fcenter[1]*fcenter[1] +
25388 fcenter[2]*fcenter[2]) /
25389 (3.0 * (normal[0] * normal[0] + normal[1] * normal[1] +
25390 normal[2] * normal[2])));
25391 xta = checkpt[0] - pc[0];
25392 yta = checkpt[1] - pc[1];
25393 zta = checkpt[2] - pc[2];
25395 if ((xta * normal[0] + yta * normal[1] + zta * normal[2]) < 0) {
25397 normal[0] = -normal[0];
25398 normal[1] = -normal[1];
25399 normal[2] = -normal[2];
25402 if (xta * xta + yta * yta + zta * zta <=
25403 2.0 * (xta * (fcenter[0] - multiplier * normal[0]) +
25404 yta * (fcenter[1] - multiplier * normal[1]) +
25405 zta * (fcenter[2] - multiplier * normal[2]))) {
25409 len = distance(cent, checkpt);
25410 if ((fabs(len - rd) / rd) < b->epsilon) len = rd;
25419 if ((pa[pointmtrindex] > 0) && (pb[pointmtrindex] > 0) &&
25420 (pc[pointmtrindex] > 0)) {
25422 REAL prjpt[3], n[3];
25423 REAL a, a1, a2, a3;
25424 projpt2face(checkpt, pa, pb, pc, prjpt);
25426 facenormal(pa, pb, pc, n, 1, NULL);
25427 a = sqrt(dot(n,n));
25429 facenormal(pa, pb, prjpt, n, 1, NULL);
25430 a1 = sqrt(dot(n,n));
25431 facenormal(pb, pc, prjpt, n, 1, NULL);
25432 a2 = sqrt(dot(n,n));
25433 facenormal(pc, pa, prjpt, n, 1, NULL);
25434 a3 = sqrt(dot(n,n));
25435 if ((fabs(a1 + a2 + a3 - a) / a) < b->epsilon) {
25438 rd = a1 / a * pc[pointmtrindex]
25439 + a2 / a * pa[pointmtrindex]
25440 + a3 / a * pb[pointmtrindex];
25441 len = distance(prjpt, checkpt);
25472 int tetgenmesh::checkfac4split(face *chkfac, point& encpt,
int& qflag,
25476 REAL area, rd, len;
25477 REAL A[4][4], rhs[4], D;
25484 pa = sorg(*chkfac);
25485 pb = sdest(*chkfac);
25486 pc = sapex(*chkfac);
25489 A[0][0] = pb[0] - pa[0];
25490 A[0][1] = pb[1] - pa[1];
25491 A[0][2] = pb[2] - pa[2];
25492 A[1][0] = pc[0] - pa[0];
25493 A[1][1] = pc[1] - pa[1];
25494 A[1][2] = pc[2] - pa[2];
25495 cross(A[0], A[1], A[2]);
25497 area = 0.5 * sqrt(dot(A[2], A[2]));
25500 rhs[0] = 0.5 * dot(A[0], A[0]);
25501 rhs[1] = 0.5 * dot(A[1], A[1]);
25506 if (!lu_decmp(A, 3, indx, &D, 0)) {
25508 terminatetetgen(
this, 2);
25511 lu_solve(A, 3, indx, rhs, 0);
25512 cent[0] = pa[0] + rhs[0];
25513 cent[1] = pa[1] + rhs[1];
25514 cent[2] = pa[2] + rhs[2];
25515 rd = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
25517 if (checkconstraints && (areabound(*chkfac) > 0.0)) {
25519 if (area > areabound(*chkfac)) {
25525 if (b->fixedvolume) {
25526 if ((area * sqrt(area)) > b->maxvolume) {
25532 if (b->varvolume) {
25537 stpivot(*chkfac, adjtet);
25538 if (!ishulltet(adjtet)) {
25539 volbnd = volumebound(adjtet.tet);
25540 if ((volbnd > 0) && (area * sqrt(area)) > volbnd) {
25546 if (!ishulltet(adjtet)) {
25547 volbnd = volumebound(adjtet.tet);
25548 if ((volbnd > 0) && (area * sqrt(area)) > volbnd) {
25557 if (((pa[pointmtrindex] > 0) && (rd > pa[pointmtrindex])) ||
25558 ((pb[pointmtrindex] > 0) && (rd > pb[pointmtrindex])) ||
25559 ((pc[pointmtrindex] > 0) && (rd > pc[pointmtrindex]))) {
25569 for (i = 0; i < 2; i++) {
25570 stpivot(*chkfac, searchtet);
25571 if (!ishulltet(searchtet)) {
25572 int encroached = 0;
25574 len = distance(oppo(searchtet), cent);
25575 if ((fabs(len - rd) / rd) < b->epsilon) len = rd;
25577 if (b->use_equatorial_lens) {
25578 point tettapex = oppo(searchtet);
25579 REAL normal[3], fcenter[3];
25580 REAL xta, yta, zta;
25583 point fa = org(searchtet);
25584 point fb = dest(searchtet);
25585 point fc = apex(searchtet);
25587 fcenter[0] = cent[0] - fc[0];
25588 fcenter[1] = cent[1] - fc[1];
25589 fcenter[2] = cent[2] - fc[2];
25591 facenormal(fa, fb, fc, normal, 1, NULL);
25592 multiplier = 0.985 * sqrt((fcenter[0]*fcenter[0] + fcenter[1]*fcenter[1] +
25593 fcenter[2]*fcenter[2]) /
25594 (3.0 * (normal[0] * normal[0] + normal[1] * normal[1] +
25595 normal[2] * normal[2])));
25596 xta = tettapex[0] - fc[0];
25597 yta = tettapex[1] - fc[1];
25598 zta = tettapex[2] - fc[2];
25599 if (xta * xta + yta * yta + zta * zta <=
25600 2.0 * (xta * (fcenter[0] - multiplier * normal[0]) +
25601 yta * (fcenter[1] - multiplier * normal[1]) +
25602 zta * (fcenter[2] - multiplier * normal[2]))) {
25614 encpt = oppo(searchtet);
25618 encpt = oppo(searchtet);
25624 sesymself(*chkfac);
25627 return encpt != NULL;
25650 int tetgenmesh::splitsubface(face *splitfac, point encpt, point encpt1,
25651 int qflag, REAL *ccent,
int chkencflag)
25654 if (!qflag && smarktest3ed(*splitfac)) {
25660 if (checkconstraints) {
25663 if (areabound(*splitfac) == 0) {
25671 if (useinsertradius) {
25672 if (encpt != NULL) {
25674 REAL rv = distance(encpt, ccent);
25675 if (pointtype(encpt) == FREESEGVERTEX) {
25677 sdecode(point2sh(encpt), parentseg);
25678 if (segfacetadjacent(&parentseg, splitfac)) {
25679 rp = getpointinsradius(encpt);
25680 if (rv < (sqrt(2.0) * rp)) {
25685 }
else if (pointtype(encpt) == FREEFACETVERTEX) {
25687 sdecode(point2sh(encpt), parentsh);
25688 if (facetfacetadjacent(&parentsh, splitfac)) {
25689 rp = getpointinsradius(encpt);
25699 insertvertexflags ivf;
25704 makepoint(&newpt, FREEFACETVERTEX);
25706 for (i = 0; i < 3; i++) newpt[i] = ccent[i];
25709 searchsh = *splitfac;
25713 calculateabovepoint4(newpt, sorg(*splitfac), sdest(*splitfac),
25718 ivf.iloc = (int) slocate(newpt, &searchsh, 1, 0, 0);
25720 if (!((ivf.iloc == (
int) ONFACE) || (ivf.iloc == (
int) ONEDGE))) {
25722 pointdealloc(newpt);
25724 smarktest3(*splitfac);
25732 stpivot(searchsh, searchtet);
25739 ivf.chkencflag = chkencflag;
25740 ivf.sloc = (int) INSTAR;
25742 ivf.splitbdflag = 1;
25744 ivf.respectbdflag = 1;
25745 ivf.assignmeshsize = b->metric;
25746 ivf.refineflag = 2;
25747 ivf.refinesh = *splitfac;
25748 ivf.smlenflag = useinsertradius;
25751 if (insertpoint(newpt, &searchtet, &searchsh, NULL, &ivf)) {
25753 if (steinerleft > 0) steinerleft--;
25754 if (useinsertradius) {
25755 save_facetpoint_insradius(newpt, ivf.parentpt, ivf.smlen);
25757 if (flipstack != NULL) {
25758 flipconstraints fc;
25759 fc.chkencflag = chkencflag;
25762 unflipqueue->restart();
25767 pointdealloc(newpt);
25768 if (ivf.iloc == (
int) ENCSEGMENT) {
25772 for (i = 0; i < encseglist->objects; i++) {
25773 paryseg = (face *) fastlookup(encseglist, i);
25774 if (splitsegment(paryseg, NULL, 0.0, encpt, encpt1, qflag,
25780 encseglist->restart();
25783 if (badsubsegs->items > 0) {
25784 repairencsegs(chkencflag | 1);
25789 if (ivf.iloc == (
int) NEARVERTEX) {
25790 terminatetetgen(
this, 2);
25794 smarktest3(*splitfac);
25805 void tetgenmesh::repairencfacs(
int chkencflag)
25808 point encpt = NULL;
25814 while ((badsubfacs->items > 0) && (steinerleft != 0)) {
25815 badsubfacs->traversalinit();
25816 bface = (face *) badsubfacs->traverse();
25817 while ((bface != NULL) && (steinerleft != 0)) {
25819 if (bface->shver >= 0) {
25821 if ((bface->sh != NULL) && (bface->sh[3] != NULL)) {
25823 if (smarktest2ed(*bface)) {
25824 sunmarktest2(*bface);
25825 if (checkfac4split(bface, encpt, qflag, ccent)) {
25826 splitsubface(bface, encpt, NULL, qflag, ccent, chkencflag);
25831 badsubfacs->dealloc((
void *) bface);
25833 bface = (face *) badsubfacs->traverse();
25837 if (badsubfacs->items > 0) {
25838 if (steinerleft == 0) {
25840 printf(
"The desired number of Steiner points is reached.\n");
25843 terminatetetgen(
this, 2);
25845 badsubfacs->traversalinit();
25846 bface = (face *) badsubfacs->traverse();
25847 while (bface != NULL) {
25849 if (bface->shver >= 0) {
25850 if ((bface->sh != NULL) && (bface->sh[3] != NULL)) {
25851 if (smarktest2ed(*bface)) {
25852 sunmarktest2(*bface);
25856 bface = (face *) badsubfacs->traverse();
25858 badsubfacs->restart();
25868 int tetgenmesh::checktet4split(triface *chktet,
int &qflag, REAL *ccent)
25870 point pa, pb, pc, pd, *ppt;
25871 REAL vda[3], vdb[3], vdc[3];
25872 REAL vab[3], vbc[3], vca[3];
25873 REAL N[4][3], L[4], cosd[6], elen[6];
25874 REAL maxcosd, vol, volbnd, smlen = 0, rd;
25875 REAL A[4][4], rhs[4], D;
25881 if (elemattribute(chktet->tet, numelemattrib - 1) == -1.0) {
25888 pd = (point) chktet->tet[7];
25889 if (pd == dummypoint) {
25893 pa = (point) chktet->tet[4];
25894 pb = (point) chktet->tet[5];
25895 pc = (point) chktet->tet[6];
25899 for (i = 0; i < 3; i++) A[0][i] = vda[i] = pa[i] - pd[i];
25900 for (i = 0; i < 3; i++) A[1][i] = vdb[i] = pb[i] - pd[i];
25901 for (i = 0; i < 3; i++) A[2][i] = vdc[i] = pc[i] - pd[i];
25904 for (i = 0; i < 3; i++) vab[i] = pb[i] - pa[i];
25905 for (i = 0; i < 3; i++) vbc[i] = pc[i] - pb[i];
25906 for (i = 0; i < 3; i++) vca[i] = pa[i] - pc[i];
25908 if (!lu_decmp(A, 3, indx, &D, 0)) {
25916 if (b->varvolume || b->fixedvolume) {
25917 vol = fabs(A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
25918 if (b->fixedvolume) {
25919 if (vol > b->maxvolume) {
25923 if (!qflag && b->varvolume) {
25924 volbnd = volumebound(chktet->tet);
25925 if ((volbnd > 0.0) && (vol > volbnd)) {
25931 rhs[0] = 0.5 * dot(vda, vda);
25932 rhs[1] = 0.5 * dot(vdb, vdb);
25933 rhs[2] = 0.5 * dot(vdc, vdc);
25934 lu_solve(A, 3, indx, rhs, 0);
25935 for (i = 0; i < 3; i++) ccent[i] = pd[i] + rhs[i];
25942 rhs[0] = 0.5 * dot(vda, vda);
25943 rhs[1] = 0.5 * dot(vdb, vdb);
25944 rhs[2] = 0.5 * dot(vdc, vdc);
25945 lu_solve(A, 3, indx, rhs, 0);
25946 for (i = 0; i < 3; i++) ccent[i] = pd[i] + rhs[i];
25947 rd = sqrt(dot(rhs, rhs));
25949 ppt = (point *) &(chktet->tet[4]);
25950 for (i = 0; i < 4; i++) {
25951 if (ppt[i][pointmtrindex] > 0) {
25952 if (rd > ppt[i][pointmtrindex]) {
25960 if (in->tetunsuitable != NULL) {
25962 if ((*(in->tetunsuitable))(pa, pb, pc, pd, NULL, 0)) {
25964 rhs[0] = 0.5 * dot(vda, vda);
25965 rhs[1] = 0.5 * dot(vdb, vdb);
25966 rhs[2] = 0.5 * dot(vdc, vdc);
25967 lu_solve(A, 3, indx, rhs, 0);
25968 for (i = 0; i < 3; i++) ccent[i] = pd[i] + rhs[i];
25973 if (useinsertradius) {
25981 checkedge.tet = chktet->tet;
25982 for (i = 0; i < 6; i++) {
25983 checkedge.ver = edge2ver[i];
25984 e1 = org(checkedge);
25985 e2 = dest(checkedge);
25986 elen[i] = distance(e1, e2);
25991 if (elen[i] < smlen) {
25998 checkedge.ver = edge2ver[j];
26001 e1 = org(checkedge);
26002 smrrv = getpointinsradius(e1);
26003 e2 = dest(checkedge);
26004 rrv = getpointinsradius(e2);
26016 if ((fabs(smrrv - smlen) / smlen) < b->epsilon) {
26019 if (smrrv > smlen) {
26026 if (b->minratio > 0) {
26028 rhs[0] = 0.5 * dot(vda, vda);
26029 rhs[1] = 0.5 * dot(vdb, vdb);
26030 rhs[2] = 0.5 * dot(vdc, vdc);
26031 lu_solve(A, 3, indx, rhs, 0);
26032 for (i = 0; i < 3; i++) ccent[i] = pd[i] + rhs[i];
26033 rd = sqrt(dot(rhs, rhs));
26034 if (!useinsertradius) {
26036 elen[0] = dot(vda, vda);
26037 elen[1] = dot(vdb, vdb);
26038 elen[2] = dot(vdc, vdc);
26039 elen[3] = dot(vab, vab);
26040 elen[4] = dot(vbc, vbc);
26041 elen[5] = dot(vca, vca);
26043 for (i = 1; i < 6; i++) {
26044 if (smlen > elen[i]) {
26048 smlen = sqrt(smlen);
26051 if (D > b->minratio) {
26058 if (b->mindihedral > 0) {
26060 for (j = 0; j < 3; j++) {
26061 for (i = 0; i < 3; i++) N[j][i] = 0.0;
26063 lu_solve(A, 3, indx, N[j], 0);
26065 for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
26067 for (i = 0; i < 4; i++) {
26068 L[i] = sqrt(dot(N[i], N[i]));
26070 terminatetetgen(
this, 2);
26072 for (j = 0; j < 3; j++) N[i][j] /= L[i];
26075 cosd[0] = -dot(N[0], N[1]);
26076 cosd[1] = -dot(N[0], N[2]);
26077 cosd[2] = -dot(N[0], N[3]);
26078 cosd[3] = -dot(N[1], N[2]);
26079 cosd[4] = -dot(N[1], N[3]);
26080 cosd[5] = -dot(N[2], N[3]);
26084 for (i = 1; i < 6; i++) {
26086 maxcosd = (cosd[i] > maxcosd ? cosd[i] : maxcosd);
26089 if (maxcosd > cosmindihed) {
26093 rhs[0] = 0.5 * dot(vda, vda);
26094 rhs[1] = 0.5 * dot(vdb, vdb);
26095 rhs[2] = 0.5 * dot(vdc, vdc);
26096 lu_solve(A, 3, indx, rhs, 0);
26097 for (i = 0; i < 3; i++) ccent[i] = pd[i] + rhs[i];
26113 int tetgenmesh::splittetrahedron(triface* splittet,
int qflag, REAL *ccent,
26120 insertvertexflags ivf;
26128 makepoint(&newpt, FREEVOLVERTEX);
26129 for (i = 0; i < 3; i++) newpt[i] = ccent[i];
26135 searchtet = *splittet;
26136 ivf.iloc = (int) OUTSIDE;
26137 ivf.iloc = locate(newpt, &searchtet, 1);
26139 if ((ivf.iloc == (
int) OUTSIDE) || (ivf.iloc == (
int) ENCSUBFACE)) {
26142 if (b->verbose > 2) {
26143 printf(
" New point %d is blocked by a polygon.\n", pointmark(newpt));
26146 pointdealloc(newpt);
26147 if (b->nobisect)
return 0;
26152 locateresult sloc = OUTSIDE;
26153 tspivot(searchtet, searchsh);
26154 ppt = (point *) &(searchsh.sh[3]);
26155 projpt2face(ccent, ppt[0], ppt[1], ppt[2], prjpt);
26157 sloc = slocate(prjpt, &searchsh, 0, 0, 1);
26158 if ((sloc == ONEDGE) || (sloc == ONFACE)) {
26161 REAL fcent[3], r = 0;
26162 ppt = (point *) &(searchsh.sh[3]);
26163 if (checkfac4encroach(ppt[0], ppt[1], ppt[2], ccent, fcent, &r)) {
26165 splitflag = splitsubface(&searchsh, NULL, org(*splittet), qflag,
26166 fcent, chkencflag | 2);
26169 repairencfacs(chkencflag | 2);
26173 else if ((sloc == OUTSIDE) || (sloc == ENCSEGMENT)) {
26180 if ((splittet->tet != NULL) && (splittet->tet[4] != NULL)) {
26181 enqueuetetrahedron(splittet);
26196 ivf.chkencflag = chkencflag;
26197 ivf.sloc = ivf.sbowywat = 0;
26198 ivf.splitbdflag = 0;
26200 ivf.respectbdflag = 1;
26201 ivf.assignmeshsize = b->metric;
26203 ivf.refineflag = 1;
26204 ivf.refinetet = *splittet;
26205 if (useinsertradius) {
26212 if (insertpoint(newpt, &searchtet, NULL, NULL, &ivf)) {
26215 if (steinerleft > 0) steinerleft--;
26216 if (useinsertradius) {
26217 setpointinsradius(newpt, ivf.smlen);
26218 setpoint2ppt(newpt, ivf.parentpt);
26220 if (flipstack != NULL) {
26221 flipconstraints fc;
26222 fc.chkencflag = chkencflag;
26225 unflipqueue->restart();
26230 pointdealloc(newpt);
26232 if (ivf.iloc == (
int) ENCSEGMENT) {
26233 if (!b->nobisect || checkconstraints) {
26235 for (i = 0; i < encseglist->objects; i++) {
26236 paryseg = (face *) fastlookup(encseglist, i);
26237 if (splitsegment(paryseg, NULL, rv, org(*splittet), NULL, qflag,
26244 encseglist->restart();
26247 if (badsubsegs->items > 0) {
26248 repairencsegs(chkencflag | 3);
26251 if (badsubfacs->items > 0) {
26252 repairencfacs(chkencflag | 2);
26255 }
else if (ivf.iloc == (
int) ENCSUBFACE) {
26256 if (!b->nobisect || checkconstraints) {
26258 for (i = 0; i < encshlist->objects; i++) {
26259 bface = (badface *) fastlookup(encshlist, i);
26260 if (splitsubface(&(bface->ss), NULL, org(*splittet), qflag,
26261 bface->cent, chkencflag | 2)){
26267 encshlist->restart();
26270 if (badsubfacs->items > 0) {
26271 repairencfacs(chkencflag | 2);
26275 if (ivf.iloc == (
int) NEARVERTEX) {
26276 terminatetetgen(
this, 2);
26281 if ((splittet->tet != NULL) && (splittet->tet[4] != NULL)) {
26282 enqueuetetrahedron(splittet);
26297 void tetgenmesh::repairbadtets(
int chkencflag)
26306 while ((badtetrahedrons->items > 0) && (steinerleft != 0)) {
26307 badtetrahedrons->traversalinit();
26308 bface = (triface *) badtetrahedrons->traverse();
26309 while ((bface != NULL) && (steinerleft != 0)) {
26311 if (bface->ver >= 0) {
26313 if (!isdeadtet(*bface)) {
26315 if (marktest2ed(*bface)) {
26316 unmarktest2(*bface);
26317 if (checktet4split(bface, qflag, ccent)) {
26318 splittetrahedron(bface, qflag, ccent, chkencflag);
26323 badtetrahedrons->dealloc((
void *) bface);
26325 bface = (triface *) badtetrahedrons->traverse();
26329 if (badtetrahedrons->items > 0) {
26330 if (steinerleft == 0) {
26332 printf(
"The desired number of Steiner points is reached.\n");
26335 terminatetetgen(
this, 2);
26338 badtetrahedrons->traversalinit();
26339 bface = (triface *) badtetrahedrons->traverse();
26340 while (bface != NULL) {
26342 if (bface->ver >= 0) {
26343 if (!isdeadtet(*bface)) {
26344 if (marktest2ed(*bface)) {
26345 unmarktest2(*bface);
26349 bface = (triface *) badtetrahedrons->traverse();
26352 badtetrahedrons->restart();
26362 void tetgenmesh::delaunayrefinement()
26370 long bak_segref_count, bak_facref_count, bak_volref_count;
26371 long bak_flipcount = flip23count + flip32count + flip44count;
26374 printf(
"Refining mesh...\n");
26378 printf(
" Min radius-edge ratio = %g.\n", b->minratio);
26379 printf(
" Min dihedral angle = %g.\n", b->mindihedral);
26383 steinerleft = b->steinerleft;
26384 if (steinerleft > 0) {
26386 steinercount = st_segref_count + st_facref_count + st_volref_count;
26387 if (steinercount < steinerleft) {
26388 steinerleft -= steinercount;
26391 printf(
"\nWarning: ");
26392 printf(
"The desired number of Steiner points (%d) has reached.\n\n",
26399 if (useinsertradius) {
26400 if ((b->plc && b->nobisect) || b->refine) {
26401 makesegmentendpointsmap();
26402 makefacetverticesmap();
26407 encseglist =
new arraypool(
sizeof(face), 8);
26408 encshlist =
new arraypool(
sizeof(badface), 8);
26412 if (!b->nobisect || checkconstraints) {
26414 printf(
" Splitting encroached subsegments.\n");
26418 steinercount = points->items;
26421 badsubsegs =
new memorypool(
sizeof(face), b->shellfaceperblock,
26422 sizeof(
void *), 0);
26425 subsegs->traversalinit();
26426 checkseg.sh = shellfacetraverse(subsegs);
26427 while (checkseg.sh != (shellface *) NULL) {
26428 enqueuesubface(badsubsegs, &checkseg);
26429 checkseg.sh = shellfacetraverse(subsegs);
26433 repairencsegs(chkencflag);
26436 printf(
" Added %ld Steiner points.\n", points->items - steinercount);
26439 if (b->reflevel > 1) {
26441 printf(
" Splitting encroached subfaces.\n");
26445 steinercount = points->items;
26446 bak_segref_count = st_segref_count;
26447 bak_facref_count = st_facref_count;
26450 badsubfacs =
new memorypool(
sizeof(face), b->shellfaceperblock,
26451 sizeof(
void *), 0);
26454 subfaces->traversalinit();
26455 checksh.sh = shellfacetraverse(subfaces);
26456 while (checksh.sh != (shellface *) NULL) {
26457 enqueuesubface(badsubfacs, &checksh);
26458 checksh.sh = shellfacetraverse(subfaces);
26462 repairencfacs(chkencflag);
26465 printf(
" Added %ld (%ld,%ld) Steiner points.\n",
26466 points->items-steinercount, st_segref_count-bak_segref_count,
26467 st_facref_count-bak_facref_count);
26472 if (b->reflevel > 2) {
26474 printf(
" Splitting bad quality tets.\n");
26478 steinercount = points->items;
26479 bak_segref_count = st_segref_count;
26480 bak_facref_count = st_facref_count;
26481 bak_volref_count = st_volref_count;
26484 cosmindihed = cos(b->mindihedral / 180.0 * PI);
26487 badtetrahedrons =
new memorypool(
sizeof(triface), b->tetrahedraperblock,
26488 sizeof(
void *), 0);
26490 tetrahedrons->traversalinit();
26491 checktet.tet = tetrahedrontraverse();
26492 while (checktet.tet != NULL) {
26493 enqueuetetrahedron(&checktet);
26494 checktet.tet = tetrahedrontraverse();
26498 repairbadtets(chkencflag);
26501 printf(
" Added %ld (%ld,%ld,%ld) Steiner points.\n",
26502 points->items - steinercount,
26503 st_segref_count - bak_segref_count,
26504 st_facref_count - bak_facref_count,
26505 st_volref_count - bak_volref_count);
26510 if (flip23count + flip32count + flip44count > bak_flipcount) {
26511 printf(
" Performed %ld flips.\n", flip23count + flip32count +
26512 flip44count - bak_flipcount);
26516 if (steinerleft == 0) {
26518 printf(
"\nWarnning: ");
26519 printf(
"The desired number of Steiner points (%d) is reached.\n\n",
26530 if (!b->nobisect || checkconstraints) {
26531 totalworkmemory += (badsubsegs->maxitems * badsubsegs->itembytes);
26534 if (b->reflevel > 1) {
26535 totalworkmemory += (badsubfacs->maxitems * badsubfacs->itembytes);
26540 if (b->reflevel > 2) {
26541 totalworkmemory += (badtetrahedrons->maxitems*badtetrahedrons->itembytes);
26542 delete badtetrahedrons;
26543 badtetrahedrons = NULL;
26561 long tetgenmesh::lawsonflip3d(flipconstraints *fc)
26563 triface fliptets[5], neightet, hulltet;
26564 face checksh, casingout;
26565 badface *popface, *bface;
26566 point pd, pe, *pts;
26569 long flipcount, totalcount = 0l;
26570 long sliver_peels = 0l;
26577 if (b->verbose > 2) {
26578 printf(
" Lawson flip %ld faces.\n", flippool->items);
26582 while (flipstack != (badface *) NULL) {
26584 popface = flipstack;
26585 fliptets[0] = popface->tt;
26586 flipstack = flipstack->nextitem;
26587 flippool->dealloc((
void *) popface);
26590 if (isdeadtet(fliptets[0]))
continue;
26592 if (!facemarked(fliptets[0]))
continue;
26594 unmarkface(fliptets[0]);
26596 if (ishulltet(fliptets[0]))
continue;
26598 fsym(fliptets[0], fliptets[1]);
26599 if (ishulltet(fliptets[1])) {
26602 tspivot(fliptets[0], checksh);
26603 for (i = 0; i < 3; i++) {
26604 if (!isshsubseg(checksh)) {
26605 spivot(checksh, casingout);
26607 if (sorg(checksh) != sdest(casingout)) sesymself(casingout);
26608 stpivot(casingout, neightet);
26609 if (neightet.tet == fliptets[0].tet) {
26612 edestoppo(neightet, hulltet);
26614 if (oppo(hulltet) == dummypoint) {
26615 pe = org(neightet);
26616 if ((pointtype(pe) == FREEFACETVERTEX) ||
26617 (pointtype(pe) == FREESEGVERTEX)) {
26618 removevertexbyflips(pe);
26621 eorgoppo(neightet, hulltet);
26623 if (oppo(hulltet) == dummypoint) {
26624 pd = dest(neightet);
26625 if ((pointtype(pd) == FREEFACETVERTEX) ||
26626 (pointtype(pd) == FREESEGVERTEX)) {
26627 removevertexbyflips(pd);
26631 fliptets[0] = neightet;
26632 fnext(fliptets[0], fliptets[1]);
26633 fnext(fliptets[1], fliptets[2]);
26634 flip32(fliptets, 1, fc);
26639 if (fc->remove_ndelaunay_edge) {
26642 tetprism_vol_sum += fc->tetprism_vol_sum;
26643 fc->tetprism_vol_sum = 0.0;
26650 senextself(checksh);
26656 if (checksubfaceflag) {
26658 if (issubface(fliptets[0]))
continue;
26662 pts = (point *) fliptets[1].tet;
26663 sign = insphere_s(pts[4], pts[5], pts[6], pts[7], oppo(fliptets[0]));
26667 pd = oppo(fliptets[0]);
26668 pe = oppo(fliptets[1]);
26672 len3 = distance(pd, pe);
26673 len3 = (len3 * len3 * len3);
26674 int round_flag = 0;
26678 for (i = 0; i < 3; i++) {
26679 ori = orient3d(org(fliptets[0]), dest(fliptets[0]), pd, pe);
26683 esym(fliptets[0], fliptets[2]);
26684 esym(fliptets[1], fliptets[3]);
26685 if (issubface(fliptets[2]) || issubface(fliptets[3])) {
26686 vol = orient3dfast(org(fliptets[0]), dest(fliptets[0]), pd, pe);
26687 if ((fabs(vol) / len3) < b->epsilon) {
26693 if (ori <= 0)
break;
26694 enextself(fliptets[0]);
26695 eprevself(fliptets[1]);
26702 flip23(fliptets, 0, fc);
26704 if (fc->remove_ndelaunay_edge) {
26707 tetprism_vol_sum += fc->tetprism_vol_sum;
26708 fc->tetprism_vol_sum = 0.0;
26714 if (checksubsegflag) {
26716 if (issubseg(fliptets[0]))
continue;
26719 esymself(fliptets[0]);
26720 for (i = 0; i < 3; i++) {
26721 fnext(fliptets[i], fliptets[i+1]);
26723 if (fliptets[3].tet == fliptets[0].tet) {
26725 flip32(fliptets, 0, fc);
26727 if (fc->remove_ndelaunay_edge) {
26730 tetprism_vol_sum += fc->tetprism_vol_sum;
26731 fc->tetprism_vol_sum = 0.0;
26736 fnext(fliptets[3], fliptets[4]);
26737 if (fliptets[4].tet == fliptets[0].tet) {
26739 if (round_flag == 1) {
26743 if (apex(fliptets[3]) == dummypoint) {
26756 esymself(fliptets[0]);
26760 flip23(fliptets, 0, fc);
26761 fnext(fliptets[3], fliptets[1]);
26762 fnext(fliptets[1], fliptets[2]);
26770 flip32(&(fliptets[1]), (apex(fliptets[3]) == dummypoint), fc);
26775 if (fc->remove_ndelaunay_edge) {
26778 tetprism_vol_sum += fc->tetprism_vol_sum;
26779 fc->tetprism_vol_sum = 0.0;
26792 unflipqueue->newindex((
void **) &bface);
26793 bface->tt = fliptets[0];
26794 bface->forg = org(fliptets[0]);
26795 bface->fdest = dest(fliptets[0]);
26796 bface->fapex = apex(fliptets[0]);
26800 if (b->verbose > 2) {
26801 if (flipcount > 0) {
26802 printf(
" Performed %ld flips.\n", flipcount);
26806 totalcount += flipcount;
26809 if (unflipqueue->objects == 0l)
break;
26811 if (flipcount == 0l)
break;
26814 for (i = 0; i < unflipqueue->objects; i++) {
26815 bface = (badface *) fastlookup(unflipqueue, i);
26816 if (!isdeadtet(bface->tt) &&
26817 (org(bface->tt) == bface->forg) &&
26818 (dest(bface->tt) == bface->fdest) &&
26819 (apex(bface->tt) == bface->fapex)) {
26820 flippush(flipstack, &(bface->tt));
26823 unflipqueue->restart();
26827 if (b->verbose > 2) {
26828 if (totalcount > 0) {
26829 printf(
" Performed %ld flips.\n", totalcount);
26831 if (sliver_peels > 0) {
26832 printf(
" Removed %ld hull slivers.\n", sliver_peels);
26834 if (unflipqueue->objects > 0l) {
26835 printf(
" %ld unflippable edges remained.\n", unflipqueue->objects);
26839 return totalcount + sliver_peels;
26848 void tetgenmesh::recoverdelaunay()
26850 arraypool *flipqueue, *nextflipqueue, *swapqueue;
26851 triface tetloop, neightet, *parytet;
26852 badface *bface, *parybface;
26854 flipconstraints fc;
26858 printf(
"Recovering Delaunayness...\n");
26861 tetprism_vol_sum = 0.0;
26864 tetrahedrons->traversalinit();
26865 tetloop.tet = tetrahedrontraverse();
26866 while (tetloop.tet != NULL) {
26867 for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
26868 decode(tetloop.tet[tetloop.ver], neightet);
26869 if (!facemarked(neightet)) {
26870 flippush(flipstack, &tetloop);
26873 ppt = (point *) &(tetloop.tet[4]);
26874 tetprism_vol_sum += tetprismvol(ppt[0], ppt[1], ppt[2], ppt[3]);
26875 tetloop.tet = tetrahedrontraverse();
26880 fc.bak_tetprism_vol = tetprism_vol_sum * b->epsilon * 1e-3;
26883 printf(
" Initial obj = %.17g\n", tetprism_vol_sum);
26886 if (b->verbose > 1) {
26887 printf(
" Recover Delaunay [Lawson] : %ld\n", flippool->items);
26891 fc.remove_ndelaunay_edge = 1;
26896 if (b->verbose > 1) {
26897 printf(
" obj (after Lawson) = %.17g\n", tetprism_vol_sum);
26900 if (unflipqueue->objects == 0l) {
26905 fc.collectnewtets = 1;
26908 autofliplinklevel = 1;
26909 b->fliplinklevel = -1;
26912 int bakmaxflipstarsize = b->flipstarsize;
26913 b->flipstarsize = 10;
26915 flipqueue =
new arraypool(
sizeof(badface), 10);
26916 nextflipqueue =
new arraypool(
sizeof(badface), 10);
26919 swapqueue = flipqueue;
26920 flipqueue = unflipqueue;
26921 unflipqueue = swapqueue;
26923 while (flipqueue->objects > 0l) {
26925 if (b->verbose > 1) {
26926 printf(
" Recover Delaunay [level = %2d] #: %ld.\n",
26927 autofliplinklevel, flipqueue->objects);
26930 for (i = 0; i < flipqueue->objects; i++) {
26931 bface = (badface *) fastlookup(flipqueue, i);
26932 if (getedge(bface->forg, bface->fdest, &bface->tt)) {
26933 if (removeedgebyflips(&(bface->tt), &fc) == 2) {
26934 tetprism_vol_sum += fc.tetprism_vol_sum;
26935 fc.tetprism_vol_sum = 0.0;
26937 for (j = 0; j < cavetetlist->objects; j++) {
26938 parytet = (triface *) fastlookup(cavetetlist, j);
26940 if (!isdeadtet(*parytet)) {
26941 for (parytet->ver = 0; parytet->ver < 4; parytet->ver++) {
26943 decode(parytet->tet[parytet->ver], neightet);
26944 if (!facemarked(neightet)) {
26945 flippush(flipstack, parytet);
26950 cavetetlist->restart();
26957 for (j = 0; j < unflipqueue->objects; j++) {
26958 bface = (badface *) fastlookup(unflipqueue, j);
26959 flipqueue->newindex((
void **) &parybface);
26960 *parybface = *bface;
26962 unflipqueue->restart();
26965 nextflipqueue->newindex((
void **) &parybface);
26966 *parybface = *bface;
26970 fc.tetprism_vol_sum = 0.0;
26975 if (b->verbose > 1) {
26976 printf(
" obj (after level %d) = %.17g.\n", autofliplinklevel,
26979 flipqueue->restart();
26982 swapqueue = flipqueue;
26983 flipqueue = nextflipqueue;
26984 nextflipqueue = swapqueue;
26986 if (flipqueue->objects > 0l) {
26988 if (autofliplinklevel >= b->delmaxfliplevel) {
26992 autofliplinklevel+=b->fliplinklevelinc;
26996 if (flipqueue->objects > 0l) {
26997 if (b->verbose > 1) {
26998 printf(
" %ld non-Delaunay edges remained.\n", flipqueue->objects);
27003 printf(
" Final obj = %.17g\n", tetprism_vol_sum);
27006 b->flipstarsize = bakmaxflipstarsize;
27008 delete nextflipqueue;
27017 int tetgenmesh::gettetrahedron(point pa, point pb, point pc, point pd,
27018 triface *searchtet)
27023 if (getedge(pa, pb, searchtet)) {
27024 spintet = *searchtet;
27026 if (apex(spintet) == pc) {
27027 *searchtet = spintet;
27030 fnextself(spintet);
27031 if (spintet.tet == searchtet->tet)
break;
27033 if (apex(*searchtet) == pc) {
27034 if (oppo(*searchtet) == pd) {
27037 fsymself(*searchtet);
27038 if (oppo(*searchtet) == pd) {
27054 long tetgenmesh::improvequalitybyflips()
27056 arraypool *flipqueue, *nextflipqueue, *swapqueue;
27057 badface *bface, *parybface;
27060 flipconstraints fc;
27061 REAL *cosdd, ncosdd[6], maxdd;
27062 long totalremcount, remcount;
27067 flipqueue =
new arraypool(
sizeof(badface), 10);
27068 nextflipqueue =
new arraypool(
sizeof(badface), 10);
27071 int bakautofliplinklevel = autofliplinklevel;
27072 int bakfliplinklevel = b->fliplinklevel;
27073 int bakmaxflipstarsize = b->flipstarsize;
27076 autofliplinklevel = 1;
27077 b->fliplinklevel = -1;
27078 b->flipstarsize = 10;
27080 fc.remove_large_angle = 1;
27082 fc.collectnewtets = 1;
27083 fc.checkflipeligibility = 1;
27085 totalremcount = 0l;
27088 swapqueue = flipqueue;
27089 flipqueue = unflipqueue;
27090 unflipqueue = swapqueue;
27092 while (flipqueue->objects > 0l) {
27096 while (flipqueue->objects > 0l) {
27097 if (b->verbose > 1) {
27098 printf(
" Improving mesh qualiy by flips [%d]#: %ld.\n",
27099 autofliplinklevel, flipqueue->objects);
27102 for (k = 0; k < flipqueue->objects; k++) {
27103 bface = (badface *) fastlookup(flipqueue, k);
27104 if (gettetrahedron(bface->forg, bface->fdest, bface->fapex,
27105 bface->foppo, &bface->tt)) {
27108 if (bface->tt.ver != 11) {
27111 ppt = (point *) & (bface->tt.tet[4]);
27112 tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3], bface->cent,
27113 &bface->key, NULL);
27114 bface->forg = ppt[0];
27115 bface->fdest = ppt[1];
27116 bface->fapex = ppt[2];
27117 bface->foppo = ppt[3];
27118 bface->tt.ver = 11;
27120 if (bface->key == 0) {
27122 ppt = (point *) & (bface->tt.tet[4]);
27123 tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3], bface->cent,
27124 &bface->key, NULL);
27126 cosdd = bface->cent;
27128 for (i = 0; (i < 6) && !remflag; i++) {
27129 if (cosdd[i] < cosmaxdihed) {
27131 bface->tt.ver = edge2ver[i];
27132 fc.cosdihed_in = cosdd[i];
27133 fc.cosdihed_out = 0.0;
27134 n = removeedgebyflips(&(bface->tt), &fc);
27138 if (fc.cosdihed_out < cosmaxdihed) {
27140 for (j = 0; j < cavetetlist->objects; j++) {
27141 parytet = (triface *) fastlookup(cavetetlist, j);
27142 if (!isdeadtet(*parytet)) {
27143 ppt = (point *) & (parytet->tet[4]);
27145 if (ppt[3] != dummypoint) {
27146 tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3], ncosdd,
27148 if (maxdd < cosmaxdihed) {
27150 nextflipqueue->newindex((
void **) &parybface);
27151 parybface->tt.tet = parytet->tet;
27152 parybface->tt.ver = 11;
27153 parybface->forg = ppt[0];
27154 parybface->fdest = ppt[1];
27155 parybface->fapex = ppt[2];
27156 parybface->foppo = ppt[3];
27157 parybface->key = maxdd;
27158 for (n = 0; n < 6; n++) {
27159 parybface->cent[n] = ncosdd[n];
27166 cavetetlist->restart();
27173 unflipqueue->newindex((
void **) &parybface);
27174 *parybface = *bface;
27179 flipqueue->restart();
27182 swapqueue = flipqueue;
27183 flipqueue = nextflipqueue;
27184 nextflipqueue = swapqueue;
27187 if (b->verbose > 1) {
27188 printf(
" Removed %ld bad tets.\n", remcount);
27190 totalremcount += remcount;
27192 if (unflipqueue->objects > 0l) {
27194 if (autofliplinklevel >= b->optlevel) {
27197 autofliplinklevel+=b->fliplinklevelinc;
27202 swapqueue = flipqueue;
27203 flipqueue = unflipqueue;
27204 unflipqueue = swapqueue;
27208 autofliplinklevel = bakautofliplinklevel;
27209 b->fliplinklevel = bakfliplinklevel;
27210 b->flipstarsize = bakmaxflipstarsize;
27213 delete nextflipqueue;
27215 return totalremcount;
27244 int tetgenmesh::smoothpoint(point smtpt, arraypool *linkfacelist,
int ccw,
27245 optparameters *opm)
27247 triface *parytet, *parytet1, swaptet;
27249 REAL fcent[3], startpt[3], nextpt[3], bestpt[3];
27250 REAL oldval, minval = 0.0, val;
27257 numdirs = (int) linkfacelist->objects;
27258 if (numdirs > opm->numofsearchdirs) {
27259 numdirs = opm->numofsearchdirs;
27263 opm->imprval = opm->initval;
27266 for (i = 0; i < 3; i++) {
27267 bestpt[i] = startpt[i] = smtpt[i];
27274 oldval = opm->imprval;
27276 for (i = 0; i < numdirs; i++) {
27278 k = (int) randomnation(linkfacelist->objects - i);
27279 parytet = (triface *) fastlookup(linkfacelist, k);
27281 pa = org(*parytet);
27282 pb = dest(*parytet);
27283 pc = apex(*parytet);
27284 for (j = 0; j < 3; j++) {
27285 fcent[j] = (pa[j] + pb[j] + pc[j]) / 3.0;
27287 for (j = 0; j < 3; j++) {
27288 nextpt[j] = startpt[j] + opm->searchstep * (fcent[j] - startpt[j]);
27291 for (j = 0; j < linkfacelist->objects; j++) {
27292 parytet = (triface *) fastlookup(linkfacelist, j);
27294 pa = org(*parytet);
27295 pb = dest(*parytet);
27297 pb = org(*parytet);
27298 pa = dest(*parytet);
27300 pc = apex(*parytet);
27301 ori = orient3d(pa, pb, pc, nextpt);
27304 if (opm->max_min_volume) {
27306 val = - orient3dfast(pa, pb, pc, nextpt);
27307 }
else if (opm->min_max_aspectratio) {
27308 val = 1.0 / tetaspectratio(pa, pb, pc, nextpt);
27309 }
else if (opm->min_max_dihedangle) {
27310 tetalldihedral(pa, pb, pc, nextpt, NULL, &maxcosd, NULL);
27311 if (maxcosd < -1) maxcosd = -1.0;
27312 val = maxcosd + 1.0;
27320 if (opm->max_min_volume) {
27322 val = - orient3dfast(pa, pb, pc, nextpt);
27329 if (val <= opm->imprval) {
27336 minval = (val < minval) ? val : minval;
27340 if (j == linkfacelist->objects) {
27342 opm->imprval = minval;
27344 for (j = 0; j < 3; j++) bestpt[j] = nextpt[j];
27347 j = linkfacelist->objects - i - 1;
27348 parytet = (triface *) fastlookup(linkfacelist, k);
27349 parytet1 = (triface *) fastlookup(linkfacelist, j);
27350 swaptet = *parytet1;
27351 *parytet1 = *parytet;
27352 *parytet = swaptet;
27355 diff = opm->imprval - oldval;
27358 if (opm->max_min_volume) {
27360 }
else if (opm->min_max_aspectratio) {
27361 if ((diff / oldval) < 1e-3) diff = 0.0;
27362 }
else if (opm->min_max_dihedangle) {
27368 terminatetetgen(
this, 2);
27374 for (j = 0; j < 3; j++) startpt[j] = bestpt[j];
27376 if ((opm->maxiter > 0) && (iter >= opm->maxiter)) {
27388 opm->smthiter = iter;
27390 for (i = 0; i < 3; i++) smtpt[i] = startpt[i];
27403 long tetgenmesh::improvequalitybysmoothing(optparameters *opm)
27405 arraypool *flipqueue, *swapqueue;
27407 badface *bface, *parybface;
27409 long totalsmtcount, smtcount;
27414 flipqueue =
new arraypool(
sizeof(badface), 10);
27417 swapqueue = flipqueue;
27418 flipqueue = unflipqueue;
27419 unflipqueue = swapqueue;
27421 totalsmtcount = 0l;
27424 while (flipqueue->objects > 0l) {
27428 if (b->verbose > 1) {
27429 printf(
" Improving mesh quality by smoothing [%d]#: %ld.\n",
27430 iter, flipqueue->objects);
27433 for (k = 0; k < flipqueue->objects; k++) {
27434 bface = (badface *) fastlookup(flipqueue, k);
27435 if (gettetrahedron(bface->forg, bface->fdest, bface->fapex,
27436 bface->foppo, &bface->tt)) {
27438 if (!marktested(bface->tt)) {
27441 ppt = (point *) & (bface->tt.tet[4]);
27442 tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3], bface->cent,
27443 &bface->key, NULL);
27444 if (bface->key < cossmtdihed) {
27447 opm->initval = bface->key + 1.0;
27448 for (i = 0; (i < 4) && !smtflag; i++) {
27449 if (pointtype(ppt[i]) == FREEVOLVERTEX) {
27450 getvertexstar(1, ppt[i], cavetetlist, NULL, NULL);
27451 opm->searchstep = 0.001;
27452 smtflag = smoothpoint(ppt[i], cavetetlist, 1, opm);
27454 while (opm->smthiter == opm->maxiter) {
27455 opm->searchstep *= 10.0;
27456 opm->initval = opm->imprval;
27458 smoothpoint(ppt[i], cavetetlist, 1, opm);
27462 if ((opm->imprval - 1.0) < cossmtdihed) {
27464 for (j = 0; j < cavetetlist->objects; j++) {
27465 parytet = (triface *) fastlookup(cavetetlist, j);
27467 if (!marktested(*parytet)) {
27470 ppt = (point *) & (parytet->tet[4]);
27471 tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3],
27472 bface->cent, &bface->key, NULL);
27473 if (bface->key < cossmtdihed) {
27475 marktest(*parytet);
27476 unflipqueue->newindex((
void **) &parybface);
27477 parybface->tt = *parytet;
27478 parybface->forg = ppt[0];
27479 parybface->fdest = ppt[1];
27480 parybface->fapex = ppt[2];
27481 parybface->foppo = ppt[3];
27482 parybface->tt.ver = 11;
27483 parybface->key = 0.0;
27489 cavetetlist->restart();
27494 marktest(bface->tt);
27495 unflipqueue->newindex((
void **) &parybface);
27496 parybface->tt = bface->tt;
27497 parybface->forg = ppt[0];
27498 parybface->fdest = ppt[1];
27499 parybface->fapex = ppt[2];
27500 parybface->foppo = ppt[3];
27501 parybface->tt.ver = 11;
27502 parybface->key = 0.0;
27509 flipqueue->restart();
27512 for (i = 0; i < unflipqueue->objects; i++) {
27513 bface = (badface *) fastlookup(unflipqueue, i);
27514 unmarktest(bface->tt);
27517 if (b->verbose > 1) {
27518 printf(
" Smooth %ld points.\n", smtcount);
27520 totalsmtcount += smtcount;
27522 if (smtcount == 0l) {
27533 swapqueue = flipqueue;
27534 flipqueue = unflipqueue;
27535 unflipqueue = swapqueue;
27540 return totalsmtcount;
27549 int tetgenmesh::splitsliver(triface *slitet, REAL cosd,
int chkencflag)
27552 triface searchtet, spintet, *parytet;
27553 point pa, pb, steinerpt;
27555 insertvertexflags ivf;
27556 REAL smtpt[3], midpt[3];
27563 edestoppo(*slitet, searchtet);
27566 if (issubseg(searchtet)) {
27572 spintet = searchtet;
27575 if (ishulltet(spintet))
break;
27577 fnextself(spintet);
27578 if (spintet.tet == searchtet.tet)
break;
27580 if (ishulltet(spintet)) {
27585 abtets =
new triface[n];
27586 spintet = searchtet;
27587 for (i = 0; i < n; i++) {
27588 abtets[i] = spintet;
27589 fnextself(spintet);
27593 for (i = 0; i < n; i++) {
27594 eprev(abtets[i], searchtet);
27595 esymself(searchtet);
27596 cavetetlist->newindex((
void **) &parytet);
27597 *parytet = searchtet;
27598 enext(abtets[i], searchtet);
27599 esymself(searchtet);
27600 cavetetlist->newindex((
void **) &parytet);
27601 *parytet = searchtet;
27605 pa = org(abtets[0]);
27606 pb = dest(abtets[0]);
27607 for (i = 0; i < 3; i++) {
27608 smtpt[i] = midpt[i] = 0.5 * (pa[i] + pb[i]);
27612 opm.min_max_dihedangle = 1;
27613 opm.initval = cosd + 1.0;
27614 opm.numofsearchdirs = 20;
27615 opm.searchstep = 0.001;
27618 success = smoothpoint(smtpt, cavetetlist, 1, &opm);
27621 while (opm.smthiter == opm.maxiter) {
27624 opm.searchstep *= 10.0;
27626 opm.initval = opm.imprval;
27628 smoothpoint(smtpt, cavetetlist, 1, &opm);
27632 cavetetlist->restart();
27641 makepoint(&steinerpt, FREEVOLVERTEX);
27642 for (i = 0; i < 3; i++) steinerpt[i] = smtpt[i];
27645 for (i = 0; i < n; i++) {
27647 caveoldtetlist->newindex((
void **) &parytet);
27648 *parytet = abtets[i];
27651 searchtet = abtets[0];
27653 locate(steinerpt, &searchtet);
27658 ivf.iloc = (int) INSTAR;
27659 ivf.chkencflag = chkencflag;
27660 ivf.assignmeshsize = b->metric;
27663 if (insertpoint(steinerpt, &searchtet, NULL, NULL, &ivf)) {
27666 if (steinerleft > 0) steinerleft--;
27670 pointdealloc(steinerpt);
27681 long tetgenmesh::removeslivers(
int chkencflag)
27683 arraypool *flipqueue, *swapqueue;
27684 badface *bface, *parybface;
27685 triface slitet, *parytet;
27687 REAL cosdd[6], maxcosd;
27688 long totalsptcount, sptcount;
27692 flipqueue =
new arraypool(
sizeof(badface), 10);
27695 swapqueue = flipqueue;
27696 flipqueue = unflipqueue;
27697 unflipqueue = swapqueue;
27699 totalsptcount = 0l;
27702 while ((flipqueue->objects > 0l) && (steinerleft != 0)) {
27706 if (b->verbose > 1) {
27707 printf(
" Splitting bad quality tets [%d]#: %ld.\n",
27708 iter, flipqueue->objects);
27711 for (k = 0; (k < flipqueue->objects) && (steinerleft != 0); k++) {
27712 bface = (badface *) fastlookup(flipqueue, k);
27713 if (gettetrahedron(bface->forg, bface->fdest, bface->fapex,
27714 bface->foppo, &bface->tt)) {
27715 if ((bface->key == 0) || (bface->tt.ver != 11)) {
27718 ppt = (point *) & (bface->tt.tet[4]);
27719 tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3], bface->cent,
27720 &bface->key, NULL);
27722 if (bface->key < cosslidihed) {
27724 slitet.tet = bface->tt.tet;
27726 for (j = 0; j < 6; j++) {
27727 if (bface->cent[j] < cosslidihed) {
27729 slitet.ver = edge2ver[j];
27730 if (splitsliver(&slitet, bface->cent[j], chkencflag)) {
27738 badtetrahedrons->traversalinit();
27739 parytet = (triface *) badtetrahedrons->traverse();
27740 while (parytet != NULL) {
27741 unmarktest2(*parytet);
27742 ppt = (point *) & (parytet->tet[4]);
27743 tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3], cosdd,
27745 if (maxcosd < cosslidihed) {
27747 unflipqueue->newindex((
void **) &parybface);
27748 parybface->forg = ppt[0];
27749 parybface->fdest = ppt[1];
27750 parybface->fapex = ppt[2];
27751 parybface->foppo = ppt[3];
27752 parybface->tt.tet = parytet->tet;
27753 parybface->tt.ver = 11;
27754 parybface->key = maxcosd;
27755 for (i = 0; i < 6; i++) {
27756 parybface->cent[i] = cosdd[i];
27759 parytet = (triface *) badtetrahedrons->traverse();
27761 badtetrahedrons->restart();
27764 unflipqueue->newindex((
void **) &parybface);
27765 *parybface = *bface;
27771 flipqueue->restart();
27773 if (b->verbose > 1) {
27774 printf(
" Split %ld tets.\n", sptcount);
27776 totalsptcount += sptcount;
27778 if (sptcount == 0l) {
27789 swapqueue = flipqueue;
27790 flipqueue = unflipqueue;
27791 unflipqueue = swapqueue;
27796 return totalsptcount;
27805 void tetgenmesh::optimizemesh()
27807 badface *parybface;
27812 REAL ncosdd[6], maxdd;
27813 long totalremcount, remcount;
27814 long totalsmtcount, smtcount;
27815 long totalsptcount, sptcount;
27821 printf(
"Optimizing mesh...\n");
27824 optpasses = ((1 << b->optlevel) - 1);
27827 printf(
" Optimization level = %d.\n", b->optlevel);
27828 printf(
" Optimization scheme = %d.\n", b->optscheme);
27829 printf(
" Number of iteration = %d.\n", optpasses);
27830 printf(
" Min_Max dihed angle = %g.\n", b->optmaxdihedral);
27833 totalsmtcount = totalsptcount = totalremcount = 0l;
27835 cosmaxdihed = cos(b->optmaxdihedral / 180.0 * PI);
27836 cossmtdihed = cos(b->optminsmtdihed / 180.0 * PI);
27837 cosslidihed = cos(b->optminslidihed / 180.0 * PI);
27839 int attrnum = numelemattrib - 1;
27842 tetrahedrons->traversalinit();
27843 checktet.tet = tetrahedrontraverse();
27844 while (checktet.tet != NULL) {
27847 if (elemattribute(checktet.tet, attrnum) == -1.0) {
27848 checktet.tet = tetrahedrontraverse();
27852 ppt = (point *) & (checktet.tet[4]);
27853 tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3], ncosdd, &maxdd, NULL);
27854 if (maxdd < cosmaxdihed) {
27856 unflipqueue->newindex((
void **) &parybface);
27857 parybface->tt.tet = checktet.tet;
27858 parybface->tt.ver = 11;
27859 parybface->forg = ppt[0];
27860 parybface->fdest = ppt[1];
27861 parybface->fapex = ppt[2];
27862 parybface->foppo = ppt[3];
27863 parybface->key = maxdd;
27864 for (n = 0; n < 6; n++) {
27865 parybface->cent[n] = ncosdd[n];
27868 checktet.tet = tetrahedrontraverse();
27871 totalremcount = improvequalitybyflips();
27873 if ((unflipqueue->objects > 0l) &&
27874 ((b->optscheme & 2) || (b->optscheme & 4))) {
27876 badtetrahedrons =
new memorypool(
sizeof(triface), b->tetrahedraperblock,
27877 sizeof(
void *), 0);
27880 opm.min_max_dihedangle = 1;
27881 opm.numofsearchdirs = 10;
27888 while (iter < optpasses) {
27889 smtcount = sptcount = remcount = 0l;
27890 if (b->optscheme & 2) {
27891 smtcount += improvequalitybysmoothing(&opm);
27892 totalsmtcount += smtcount;
27893 if (smtcount > 0l) {
27894 remcount = improvequalitybyflips();
27895 totalremcount += remcount;
27898 if (unflipqueue->objects > 0l) {
27899 if (b->optscheme & 4) {
27900 sptcount += removeslivers(chkencflag);
27901 totalsptcount += sptcount;
27902 if (sptcount > 0l) {
27903 remcount = improvequalitybyflips();
27904 totalremcount += remcount;
27908 if (unflipqueue->objects > 0l) {
27909 if (remcount > 0l) {
27919 delete badtetrahedrons;
27920 badtetrahedrons = NULL;
27923 if (unflipqueue->objects > 0l) {
27924 if (b->verbose > 1) {
27925 printf(
" %ld bad tets remained.\n", unflipqueue->objects);
27927 unflipqueue->restart();
27931 if (totalremcount > 0l) {
27932 printf(
" Removed %ld edges.\n", totalremcount);
27934 if (totalsmtcount > 0l) {
27935 printf(
" Smoothed %ld points.\n", totalsmtcount);
27937 if (totalsptcount > 0l) {
27938 printf(
" Split %ld slivers.\n", totalsptcount);
27959 void tetgenmesh::printfcomma(
unsigned long n)
27961 unsigned long n2 = 0;
27963 while (n >= 1000) {
27964 n2 = n2 + scale * (n % 1000);
27969 while (scale != 1) {
27973 printf (
",%03ld", n);
27986 int tetgenmesh::checkmesh(
int topoflag)
27988 triface tetloop, neightet, symtet;
27989 point pa, pb, pc, pd;
27994 printf(
" Checking consistency of mesh...\n");
28000 tetrahedrons->traversalinit();
28001 tetloop.tet = alltetrahedrontraverse();
28002 while (tetloop.tet != (tetrahedron *) NULL) {
28004 for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
28006 pb = dest(tetloop);
28007 pc = apex(tetloop);
28008 pd = oppo(tetloop);
28009 if (tetloop.ver == 0) {
28010 if (!ishulltet(tetloop)) {
28012 ori = orient3d(pa, pb, pc, pd);
28014 printf(
" !! !! %s ", ori > 0.0 ?
"Inverted" :
"Degenerated");
28015 printf(
" (%d, %d, %d, %d) (ori = %.17g)\n", pointmark(pa),
28016 pointmark(pb), pointmark(pc), pointmark(pd), ori);
28021 if (infected(tetloop)) {
28023 printf(
" !! (%d, %d, %d, %d) is infected.\n", pointmark(pa),
28024 pointmark(pb), pointmark(pc), pointmark(pd));
28027 if (marktested(tetloop)) {
28029 printf(
" !! (%d, %d, %d, %d) is marked.\n", pointmark(pa),
28030 pointmark(pb), pointmark(pc), pointmark(pd));
28034 if (tetloop.tet[tetloop.ver] == NULL) {
28035 printf(
" !! !! No neighbor at face (%d, %d, %d).\n", pointmark(pa),
28036 pointmark(pb), pointmark(pc));
28040 fsym(tetloop, neightet);
28041 if (neightet.tet != NULL) {
28043 fsym(neightet, symtet);
28044 if ((tetloop.tet != symtet.tet) || (tetloop.ver != symtet.ver)) {
28045 printf(
" !! !! Asymmetric tetra-tetra bond:\n");
28046 if (tetloop.tet == symtet.tet) {
28047 printf(
" (Right tetrahedron, wrong orientation)\n");
28049 printf(
" First: (%d, %d, %d, %d)\n", pointmark(pa),
28050 pointmark(pb), pointmark(pc), pointmark(pd));
28051 printf(
" Second: (%d, %d, %d, %d)\n", pointmark(org(neightet)),
28052 pointmark(dest(neightet)), pointmark(apex(neightet)),
28053 pointmark(oppo(neightet)));
28057 if ((org(neightet) != pb) || (dest(neightet) != pa)) {
28058 printf(
" !! !! Wrong edge-edge bond:\n");
28059 printf(
" First: (%d, %d, %d, %d)\n", pointmark(pa),
28060 pointmark(pb), pointmark(pc), pointmark(pd));
28061 printf(
" Second: (%d, %d, %d, %d)\n", pointmark(org(neightet)),
28062 pointmark(dest(neightet)), pointmark(apex(neightet)),
28063 pointmark(oppo(neightet)));
28067 if (apex(neightet) != pc) {
28068 printf(
" !! !! Wrong face-face bond:\n");
28069 printf(
" First: (%d, %d, %d, %d)\n", pointmark(pa),
28070 pointmark(pb), pointmark(pc), pointmark(pd));
28071 printf(
" Second: (%d, %d, %d, %d)\n", pointmark(org(neightet)),
28072 pointmark(dest(neightet)), pointmark(apex(neightet)),
28073 pointmark(oppo(neightet)));
28077 if (oppo(neightet) == pd) {
28078 printf(
" !! !! Two identical tetra:\n");
28079 printf(
" First: (%d, %d, %d, %d)\n", pointmark(pa),
28080 pointmark(pb), pointmark(pc), pointmark(pd));
28081 printf(
" Second: (%d, %d, %d, %d)\n", pointmark(org(neightet)),
28082 pointmark(dest(neightet)), pointmark(apex(neightet)),
28083 pointmark(oppo(neightet)));
28087 printf(
" !! !! Tet-face has no neighbor (%d, %d, %d) - %d:\n",
28088 pointmark(pa), pointmark(pb), pointmark(pc), pointmark(pd));
28092 if (facemarked(tetloop)) {
28094 printf(
" !! tetface (%d, %d, %d) %d is marked.\n", pointmark(pa),
28095 pointmark(pb), pointmark(pc), pointmark(pd));
28099 for (i = 0; i < 6; i++) {
28100 tetloop.ver = edge2ver[i];
28101 if (edgemarked(tetloop)) {
28103 printf(
" !! tetedge (%d, %d) %d, %d is marked.\n",
28104 pointmark(org(tetloop)), pointmark(dest(tetloop)),
28105 pointmark(apex(tetloop)), pointmark(oppo(tetloop)));
28108 tetloop.tet = alltetrahedrontraverse();
28110 if (horrors == 0) {
28112 printf(
" In my studied opinion, the mesh appears to be consistent.\n");
28115 printf(
" !! !! !! !! %d %s witnessed.\n", horrors,
28116 horrors > 1 ?
"abnormity" :
"abnormities");
28128 int tetgenmesh::checkshells()
28130 triface neightet, symtet;
28131 face shloop, spinsh, nextsh;
28138 printf(
" Checking consistency of the mesh boundary...\n");
28142 void **bakpathblock = subfaces->pathblock;
28143 void *bakpathitem = subfaces->pathitem;
28144 int bakpathitemsleft = subfaces->pathitemsleft;
28145 int bakalignbytes = subfaces->alignbytes;
28147 subfaces->traversalinit();
28148 shloop.sh = shellfacetraverse(subfaces);
28149 while (shloop.sh != NULL) {
28151 for (i = 0; i < 3; i++) {
28154 pb = sdest(shloop);
28156 spivot(spinsh, nextsh);
28157 bakcount = horrors;
28158 while ((nextsh.sh != NULL) && (nextsh.sh != shloop.sh)) {
28159 if (nextsh.sh[3] == NULL) {
28160 printf(
" !! !! Wrong subface-subface connection (Dead subface).\n");
28161 printf(
" First: x%lx (%d, %d, %d).\n", (uintptr_t) spinsh.sh,
28162 pointmark(sorg(spinsh)), pointmark(sdest(spinsh)),
28163 pointmark(sapex(spinsh)));
28164 printf(
" Second: x%lx (DEAD)\n", (uintptr_t) nextsh.sh);
28169 if (!(((sorg(nextsh) == pa) && (sdest(nextsh) == pb)) ||
28170 ((sorg(nextsh) == pb) && (sdest(nextsh) == pa)))) {
28171 printf(
" !! !! Wrong subface-subface connection.\n");
28172 printf(
" First: x%lx (%d, %d, %d).\n", (uintptr_t) spinsh.sh,
28173 pointmark(sorg(spinsh)), pointmark(sdest(spinsh)),
28174 pointmark(sapex(spinsh)));
28175 printf(
" Scond: x%lx (%d, %d, %d).\n", (uintptr_t) nextsh.sh,
28176 pointmark(sorg(nextsh)), pointmark(sdest(nextsh)),
28177 pointmark(sapex(nextsh)));
28182 if (sapex(nextsh) == sapex(spinsh)) {
28183 printf(
" !! !! Existing two duplicated subfaces.\n");
28184 printf(
" First: x%lx (%d, %d, %d).\n", (uintptr_t) spinsh.sh,
28185 pointmark(sorg(spinsh)), pointmark(sdest(spinsh)),
28186 pointmark(sapex(spinsh)));
28187 printf(
" Scond: x%lx (%d, %d, %d).\n", (uintptr_t) nextsh.sh,
28188 pointmark(sorg(nextsh)), pointmark(sdest(nextsh)),
28189 pointmark(sapex(nextsh)));
28194 spivot(spinsh, nextsh);
28197 sspivot(shloop, checkseg);
28198 if (checkseg.sh != NULL) {
28199 if (checkseg.sh[3] == NULL) {
28200 printf(
" !! !! Wrong subface-subseg connection (Dead subseg).\n");
28201 printf(
" Sub: x%lx (%d, %d, %d).\n", (uintptr_t) shloop.sh,
28202 pointmark(sorg(shloop)), pointmark(sdest(shloop)),
28203 pointmark(sapex(shloop)));
28204 printf(
" Sub: x%lx (Dead)\n", (uintptr_t) checkseg.sh);
28207 if (!(((sorg(checkseg) == pa) && (sdest(checkseg) == pb)) ||
28208 ((sorg(checkseg) == pb) && (sdest(checkseg) == pa)))) {
28209 printf(
" !! !! Wrong subface-subseg connection.\n");
28210 printf(
" Sub: x%lx (%d, %d, %d).\n", (uintptr_t) shloop.sh,
28211 pointmark(sorg(shloop)), pointmark(sdest(shloop)),
28212 pointmark(sapex(shloop)));
28213 printf(
" Seg: x%lx (%d, %d).\n", (uintptr_t) checkseg.sh,
28214 pointmark(sorg(checkseg)), pointmark(sdest(checkseg)));
28219 if (horrors > bakcount)
break;
28220 senextself(shloop);
28223 stpivot(shloop, neightet);
28224 if (neightet.tet != NULL) {
28225 if (neightet.tet[4] == NULL) {
28226 printf(
" !! !! Wrong sub-to-tet connection (Dead tet)\n");
28227 printf(
" Sub: x%lx (%d, %d, %d).\n", (uintptr_t) shloop.sh,
28228 pointmark(sorg(shloop)), pointmark(sdest(shloop)),
28229 pointmark(sapex(shloop)));
28230 printf(
" Tet: x%lx (DEAD)\n", (uintptr_t) neightet.tet);
28233 if (!((sorg(shloop) == org(neightet)) &&
28234 (sdest(shloop) == dest(neightet)))) {
28235 printf(
" !! !! Wrong sub-to-tet connection\n");
28236 printf(
" Sub: x%lx (%d, %d, %d).\n", (uintptr_t) shloop.sh,
28237 pointmark(sorg(shloop)), pointmark(sdest(shloop)),
28238 pointmark(sapex(shloop)));
28239 printf(
" Tet: x%lx (%d, %d, %d, %d).\n",
28240 (uintptr_t) neightet.tet, pointmark(org(neightet)),
28241 pointmark(dest(neightet)), pointmark(apex(neightet)),
28242 pointmark(oppo(neightet)));
28245 tspivot(neightet, spinsh);
28246 if (!((sorg(spinsh) == org(neightet)) &&
28247 (sdest(spinsh) == dest(neightet)))) {
28248 printf(
" !! !! Wrong tet-sub connection.\n");
28249 printf(
" Sub: x%lx (%d, %d, %d).\n", (uintptr_t) spinsh.sh,
28250 pointmark(sorg(spinsh)), pointmark(sdest(spinsh)),
28251 pointmark(sapex(spinsh)));
28252 printf(
" Tet: x%lx (%d, %d, %d, %d).\n",
28253 (uintptr_t) neightet.tet, pointmark(org(neightet)),
28254 pointmark(dest(neightet)), pointmark(apex(neightet)),
28255 pointmark(oppo(neightet)));
28258 fsym(neightet, symtet);
28259 tspivot(symtet, spinsh);
28260 if (spinsh.sh != NULL) {
28261 if (!((sorg(spinsh) == org(symtet)) &&
28262 (sdest(spinsh) == dest(symtet)))) {
28263 printf(
" !! !! Wrong tet-sub connection.\n");
28264 printf(
" Sub: x%lx (%d, %d, %d).\n", (uintptr_t) spinsh.sh,
28265 pointmark(sorg(spinsh)), pointmark(sdest(spinsh)),
28266 pointmark(sapex(spinsh)));
28267 printf(
" Tet: x%lx (%d, %d, %d, %d).\n",
28268 (uintptr_t) symtet.tet, pointmark(org(symtet)),
28269 pointmark(dest(symtet)), pointmark(apex(symtet)),
28270 pointmark(oppo(symtet)));
28274 printf(
" Warning: Broken tet-sub-tet connection.\n");
28278 if (sinfected(shloop)) {
28280 printf(
" !! A infected subface: (%d, %d, %d).\n",
28281 pointmark(sorg(shloop)), pointmark(sdest(shloop)),
28282 pointmark(sapex(shloop)));
28284 if (smarktested(shloop)) {
28286 printf(
" !! A marked subface: (%d, %d, %d).\n", pointmark(sorg(shloop)),
28287 pointmark(sdest(shloop)), pointmark(sapex(shloop)));
28289 shloop.sh = shellfacetraverse(subfaces);
28292 if (horrors == 0) {
28294 printf(
" Mesh boundaries connected correctly.\n");
28297 printf(
" !! !! !! !! %d boundary connection viewed with horror.\n",
28301 subfaces->pathblock = bakpathblock;
28302 subfaces->pathitem = bakpathitem;
28303 subfaces->pathitemsleft = bakpathitemsleft;
28304 subfaces->alignbytes = bakalignbytes;
28315 int tetgenmesh::checksegments()
28317 triface tetloop, neightet, spintet;
28319 face neighsh, spinsh, checksh;
28320 face sseg, checkseg;
28328 printf(
" Checking tet->seg connections...\n");
28332 tetrahedrons->traversalinit();
28333 tetloop.tet = tetrahedrontraverse();
28334 while (tetloop.tet != NULL) {
28336 if (tetloop.tet[8] != NULL) {
28337 segs = (shellface *) tetloop.tet[8];
28338 for (i = 0; i < 6; i++) {
28339 sdecode(segs[i], sseg);
28340 if (sseg.sh != NULL) {
28342 tetloop.ver = edge2ver[i];
28344 pa = (point) sseg.sh[3];
28345 pb = (point) sseg.sh[4];
28346 if (!(((org(tetloop) == pa) && (dest(tetloop) == pb)) ||
28347 ((org(tetloop) == pb) && (dest(tetloop) == pa)))) {
28348 printf(
" !! Wrong tet-seg connection.\n");
28349 printf(
" Tet: x%lx (%d, %d, %d, %d) - Seg: x%lx (%d, %d).\n",
28350 (uintptr_t) tetloop.tet, pointmark(org(tetloop)),
28351 pointmark(dest(tetloop)), pointmark(apex(tetloop)),
28352 pointmark(oppo(tetloop)), (uintptr_t) sseg.sh,
28353 pointmark(pa), pointmark(pb));
28357 neightet = tetloop;
28359 tsspivot1(neightet, checkseg);
28360 if (checkseg.sh != sseg.sh) {
28361 printf(
" !! Wrong tet->seg connection.\n");
28362 printf(
" Tet: x%lx (%d, %d, %d, %d) - ",
28363 (uintptr_t) neightet.tet, pointmark(org(neightet)),
28364 pointmark(dest(neightet)), pointmark(apex(neightet)),
28365 pointmark(oppo(neightet)));
28366 if (checkseg.sh != NULL) {
28367 printf(
"Seg x%lx (%d, %d).\n", (uintptr_t) checkseg.sh,
28368 pointmark(sorg(checkseg)),pointmark(sdest(checkseg)));
28370 printf(
"Seg: NULL.\n");
28374 fnextself(neightet);
28375 }
while (neightet.tet != tetloop.tet);
28378 sstpivot1(sseg, neightet);
28379 if (neightet.tet == NULL) {
28380 printf(
" !! Wrong seg->tet connection (A NULL tet).\n");
28383 if (!(((org(neightet) == pa) && (dest(neightet) == pb)) ||
28384 ((org(neightet) == pb) && (dest(neightet) == pa)))) {
28385 printf(
" !! Wrong seg->tet connection (Wrong edge).\n");
28386 printf(
" Tet: x%lx (%d, %d, %d, %d) - Seg: x%lx (%d, %d).\n",
28387 (uintptr_t) neightet.tet, pointmark(org(neightet)),
28388 pointmark(dest(neightet)), pointmark(apex(neightet)),
28389 pointmark(oppo(neightet)), (uintptr_t) sseg.sh,
28390 pointmark(pa), pointmark(pb));
28398 neightet.tet = tetloop.tet;
28399 for (i = 0; i < 6; i++) {
28400 neightet.ver = edge2ver[i];
28401 if (edgemarked(neightet)) {
28403 printf(
" !! A marked edge: (%d, %d, %d, %d) -- x%lx %d.\n",
28404 pointmark(org(neightet)), pointmark(dest(neightet)),
28405 pointmark(apex(neightet)), pointmark(oppo(neightet)),
28406 (uintptr_t) neightet.tet, neightet.ver);
28408 spintet = neightet;
28410 fnextself(spintet);
28411 if (!edgemarked(spintet)) {
28412 printf(
" !! !! An unmarked edge (%d, %d, %d, %d) -- x%lx %d.\n",
28413 pointmark(org(spintet)), pointmark(dest(spintet)),
28414 pointmark(apex(spintet)), pointmark(oppo(spintet)),
28415 (uintptr_t) spintet.tet, spintet.ver);
28418 if (spintet.tet == neightet.tet)
break;
28422 tetloop.tet = tetrahedrontraverse();
28426 printf(
" Checking seg->tet connections...\n");
28430 subsegs->traversalinit();
28432 sseg.sh = shellfacetraverse(subsegs);
28433 while (sseg.sh != NULL) {
28436 spivot(sseg, neighsh);
28437 if (neighsh.sh != NULL) {
28441 if (((sorg(spinsh) == pa) && (sdest(spinsh) == pb)) ||
28442 ((sorg(spinsh) == pb) && (sdest(spinsh) == pa))) {
28452 stpivot(spinsh, spintet);
28453 if (spintet.tet != NULL) {
28456 tsspivot1(spintet, checkseg);
28457 if (checkseg.sh == NULL) {
28458 printf(
" !! !! No seg at tet (%d, %d, %d, %d) -- x%lx %d\n",
28459 pointmark(org(spintet)), pointmark(dest(spintet)),
28460 pointmark(apex(spintet)), pointmark(oppo(spintet)),
28461 (uintptr_t) spintet.tet, spintet.ver);
28464 if (checkseg.sh != sseg.sh) {
28465 printf(
" !! !! Wrong seg (%d, %d) at tet (%d, %d, %d, %d)\n",
28466 pointmark(sorg(checkseg)), pointmark(sdest(checkseg)),
28467 pointmark(org(spintet)), pointmark(dest(spintet)),
28468 pointmark(apex(spintet)), pointmark(oppo(spintet)));
28471 fnextself(spintet);
28473 tspivot(spintet, checksh);
28474 if (checksh.sh != NULL)
break;
28478 printf(
" !! Wrong seg-subface (%d, %d, %d) -- x%lx %d connect\n",
28479 pointmark(sorg(spinsh)), pointmark(sdest(spinsh)),
28480 pointmark(sapex(spinsh)), (uintptr_t) spinsh.sh,
28485 spivotself(spinsh);
28486 if (spinsh.sh == NULL)
break;
28487 if (spinsh.sh == neighsh.sh)
break;
28491 sstpivot1(sseg, neightet);
28492 if (neightet.tet == NULL) {
28495 sseg.sh = shellfacetraverse(subsegs);
28499 printf(
" Checking seg->seg connections...\n");
28502 points->traversalinit();
28503 pa = pointtraverse();
28504 while (pa != NULL) {
28505 if (pointtype(pa) == FREESEGVERTEX) {
28508 sdecode(point2sh(pa), sseg);
28509 if ((sseg.sh == NULL) || sseg.sh[3] == NULL) {
28510 printf(
" !! Dead point-to-seg pointer at point %d.\n",
28515 if (sorg(sseg) != pa) {
28516 if (sdest(sseg) != pa) {
28517 printf(
" !! Wrong point-to-seg pointer at point %d.\n",
28522 senext(sseg, checkseg);
28523 if ((checkseg.sh == NULL) || (checkseg.sh[3] == NULL)) {
28524 printf(
" !! Dead seg-seg connection at point %d.\n",
28528 spivotself(checkseg);
28529 checkseg.shver = 0;
28530 if ((sorg(checkseg) != pa) && (sdest(checkseg) != pa)) {
28531 printf(
" !! Wrong seg-seg connection at point %d.\n",
28539 senext2(sseg, checkseg);
28540 if ((checkseg.sh == NULL) || (checkseg.sh[3] == NULL)) {
28541 printf(
" !! Dead seg-seg connection at point %d.\n",
28545 spivotself(checkseg);
28546 checkseg.shver = 0;
28547 if ((sorg(checkseg) != pa) && (sdest(checkseg) != pa)) {
28548 printf(
" !! Wrong seg-seg connection at point %d.\n",
28556 pa = pointtraverse();
28559 if (horrors == 0) {
28560 printf(
" Segments are connected properly.\n");
28562 printf(
" !! !! !! !! Found %d missing connections.\n", horrors);
28564 if (miscount > 0) {
28565 printf(
" !! !! Found %d missing segments.\n", miscount);
28577 int tetgenmesh::checkdelaunay(
int perturb)
28582 point pa, pb, pc, pd, pe;
28588 printf(
" Checking Delaunay property of the mesh...\n");
28595 tetrahedrons->traversalinit();
28596 tetloop.tet = tetrahedrontraverse();
28597 while (tetloop.tet != (tetrahedron *) NULL) {
28599 for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
28600 fsym(tetloop, symtet);
28603 if (((point) symtet.tet[7] != dummypoint)&&(tetloop.tet < symtet.tet)) {
28605 pb = dest(tetloop);
28606 pc = apex(tetloop);
28607 pd = oppo(tetloop);
28610 sign = insphere_s(pa, pb, pc, pd, pe);
28612 sign = insphere(pa, pb, pc, pd, pe);
28616 if (checksubfaceflag) {
28617 tspivot(tetloop, checksh);
28619 if (checksh.sh == NULL) {
28620 printf(
" !! Non-locally Delaunay (%d, %d, %d) - %d, %d\n",
28621 pointmark(pa), pointmark(pb), pointmark(pc), pointmark(pd),
28628 tetloop.tet = tetrahedrontraverse();
28631 if (horrors == 0) {
28634 printf(
" The mesh is constrained Delaunay.\n");
28636 printf(
" The mesh is Delaunay.\n");
28640 printf(
" !! !! !! !! Found %d non-Delaunay faces.\n", horrors);
28658 int tetgenmesh::checkregular(
int type)
28669 printf(
" Checking %s %s property of the mesh...\n",
28670 (type & 2) == 0 ?
"Delaunay" :
"regular",
28671 (type & 1) == 0 ?
" " :
"(s)");
28685 tetrahedrons->traversalinit();
28686 tetloop.tet = tetrahedrontraverse();
28687 while (tetloop.tet != (tetrahedron *) NULL) {
28689 for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
28690 fsym(tetloop, symtet);
28693 if (((point) symtet.tet[7] != dummypoint)&&(tetloop.tet < symtet.tet)) {
28694 p[0] = org(tetloop);
28695 p[1] = dest(tetloop);
28696 p[2] = apex(tetloop);
28697 p[3] = oppo(tetloop);
28698 p[4] = oppo(symtet);
28701 sign = insphere(p[1], p[0], p[2], p[3], p[4]);
28702 }
else if (type == 1) {
28703 sign = insphere_s(p[1], p[0], p[2], p[3], p[4]);
28704 }
else if (type == 2) {
28705 sign = orient4d(p[1], p[0], p[2], p[3], p[4],
28706 p[1][3], p[0][3], p[2][3], p[3][3], p[4][3]);
28708 sign = orient4d_s(p[1], p[0], p[2], p[3], p[4],
28709 p[1][3], p[0][3], p[2][3], p[3][3], p[4][3]);
28714 if (checksubfaceflag) {
28715 tspivot(tetloop, checksh);
28717 if (checksh.sh == NULL) {
28718 printf(
" !! Non-locally %s (%d, %d, %d) - %d, %d\n",
28719 (type & 2) == 0 ?
"Delaunay" :
"regular",
28720 pointmark(p[0]), pointmark(p[1]), pointmark(p[2]),
28721 pointmark(p[3]), pointmark(p[4]));
28727 tetloop.tet = tetrahedrontraverse();
28730 if (horrors == 0) {
28733 printf(
" The mesh is constrained %s.\n",
28734 (type & 2) == 0 ?
"Delaunay" :
"regular");
28736 printf(
" The mesh is %s.\n", (type & 2) == 0 ?
"Delaunay" :
"regular");
28740 printf(
" !! !! !! !! Found %d non-%s faces.\n", horrors,
28741 (type & 2) == 0 ?
"Delaunay" :
"regular");
28756 int tetgenmesh::checkconforming(
int flag)
28758 triface searchtet, neightet, spintet;
28761 point eorg, edest, eapex, pa, pb, pc;
28762 REAL cent[3], radius, dist, diff, rd, len;
28764 int encsubsegs, encsubfaces;
28768 REAL A[4][4], rhs[4], D;
28776 printf(
" Checking conforming property of segments...\n");
28781 subsegs->traversalinit();
28782 segloop.sh = shellfacetraverse(subsegs);
28783 while (segloop.sh != (shellface *) NULL) {
28784 eorg = (point) segloop.sh[3];
28785 edest = (point) segloop.sh[4];
28786 radius = 0.5 * distance(eorg, edest);
28787 for (i = 0; i < 3; i++) cent[i] = 0.5 * (eorg[i] + edest[i]);
28790 sstpivot1(segloop, neightet);
28791 if (neightet.tet != NULL) {
28792 spintet = neightet;
28794 eapex= apex(spintet);
28795 if (eapex != dummypoint) {
28796 dist = distance(eapex, cent);
28797 diff = dist - radius;
28798 if (fabs(diff) / radius <= b->epsilon) diff = 0.0;
28803 fnextself(spintet);
28804 if (spintet.tet == neightet.tet)
break;
28808 printf(
" !! !! Non-conforming segment: (%d, %d)\n",
28809 pointmark(eorg), pointmark(edest));
28812 segloop.sh = shellfacetraverse(subsegs);
28815 if (encsubsegs == 0) {
28817 printf(
" The segments are conforming Delaunay.\n");
28820 printf(
" !! !! %d subsegments are non-conforming.\n", encsubsegs);
28828 printf(
" Checking conforming property of subfaces...\n");
28832 subfaces->traversalinit();
28833 shloop.sh = shellfacetraverse(subfaces);
28834 while (shloop.sh != (shellface *) NULL) {
28835 pa = (point) shloop.sh[3];
28836 pb = (point) shloop.sh[4];
28837 pc = (point) shloop.sh[5];
28840 A[0][0] = pb[0] - pa[0];
28841 A[0][1] = pb[1] - pa[1];
28842 A[0][2] = pb[2] - pa[2];
28843 A[1][0] = pc[0] - pa[0];
28844 A[1][1] = pc[1] - pa[1];
28845 A[1][2] = pc[2] - pa[2];
28846 cross(A[0], A[1], A[2]);
28849 elen[0] = dot(A[0], A[0]);
28850 elen[1] = dot(A[1], A[1]);
28851 rhs[0] = 0.5 * elen[0];
28852 rhs[1] = 0.5 * elen[1];
28855 if (lu_decmp(A, 3, indx, &D, 0)) {
28856 lu_solve(A, 3, indx, rhs, 0);
28857 cent[0] = pa[0] + rhs[0];
28858 cent[1] = pa[1] + rhs[1];
28859 cent[2] = pa[2] + rhs[2];
28860 rd = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
28863 for (i = 0; i < 2; i++) {
28864 stpivot(shloop, searchtet);
28865 if (!ishulltet(searchtet)) {
28866 len = distance(oppo(searchtet), cent);
28867 if ((fabs(len - rd) / rd) < b->epsilon) len = rd;
28869 printf(
" !! !! Non-conforming subface: (%d, %d, %d)\n",
28870 pointmark(pa), pointmark(pb), pointmark(pc));
28878 shloop.sh = shellfacetraverse(subfaces);
28881 if (encsubfaces == 0) {
28883 printf(
" The subfaces are conforming Delaunay.\n");
28886 printf(
" !! !! %d subfaces are non-conforming.\n", encsubfaces);
28890 return encsubsegs + encsubfaces;
28899 void tetgenmesh::qualitystatistics()
28901 triface tetloop, neightet;
28904 REAL radiusratiotable[12];
28905 REAL aspectratiotable[12];
28906 REAL A[4][4], rhs[4], D;
28907 REAL V[6][3], N[4][3], H[4];
28908 REAL edgelength[6], alldihed[6], faceangle[3];
28909 REAL shortest, longest;
28910 REAL smallestvolume, biggestvolume;
28911 REAL smallestratio, biggestratio;
28912 REAL smallestradiusratio, biggestradiusratio;
28913 REAL smallestdiangle, biggestdiangle;
28914 REAL smallestfaangle, biggestfaangle;
28915 REAL total_tet_vol, total_tetprism_vol;
28916 REAL tetvol, minaltitude;
28917 REAL cirradius, minheightinv;
28918 REAL shortlen, longlen;
28919 REAL tetaspect, tetradius;
28920 REAL smalldiangle, bigdiangle;
28921 REAL smallfaangle, bigfaangle;
28922 unsigned long radiustable[12];
28923 unsigned long aspecttable[16];
28924 unsigned long dihedangletable[18];
28925 unsigned long faceangletable[18];
28932 triface biggestradiusratiotet;
28934 printf(
"Mesh quality statistics:\n\n");
28936 shortlen = longlen = 0.0;
28937 smalldiangle = bigdiangle = 0.0;
28938 total_tet_vol = 0.0;
28939 total_tetprism_vol = 0.0;
28941 radiusratiotable[0] = 0.707; radiusratiotable[1] = 1.0;
28942 radiusratiotable[2] = 1.1; radiusratiotable[3] = 1.2;
28943 radiusratiotable[4] = 1.4; radiusratiotable[5] = 1.6;
28944 radiusratiotable[6] = 1.8; radiusratiotable[7] = 2.0;
28945 radiusratiotable[8] = 2.5; radiusratiotable[9] = 3.0;
28946 radiusratiotable[10] = 10.0; radiusratiotable[11] = 0.0;
28948 aspectratiotable[0] = 1.5; aspectratiotable[1] = 2.0;
28949 aspectratiotable[2] = 2.5; aspectratiotable[3] = 3.0;
28950 aspectratiotable[4] = 4.0; aspectratiotable[5] = 6.0;
28951 aspectratiotable[6] = 10.0; aspectratiotable[7] = 15.0;
28952 aspectratiotable[8] = 25.0; aspectratiotable[9] = 50.0;
28953 aspectratiotable[10] = 100.0; aspectratiotable[11] = 0.0;
28955 for (i = 0; i < 12; i++) radiustable[i] = 0l;
28956 for (i = 0; i < 12; i++) aspecttable[i] = 0l;
28957 for (i = 0; i < 18; i++) dihedangletable[i] = 0l;
28958 for (i = 0; i < 18; i++) faceangletable[i] = 0l;
28960 minaltitude = xmax - xmin + ymax - ymin + zmax - zmin;
28961 minaltitude = minaltitude * minaltitude;
28962 shortest = minaltitude;
28964 smallestvolume = minaltitude;
28965 biggestvolume = 0.0;
28966 smallestratio = smallestradiusratio = 1e+16;
28967 biggestratio = biggestradiusratio = 0.0;
28968 smallestdiangle = smallestfaangle = 180.0;
28969 biggestdiangle = biggestfaangle = 0.0;
28972 int attrnum = numelemattrib - 1;
28975 tetrahedrons->traversalinit();
28976 tetloop.tet = tetrahedrontraverse();
28977 while (tetloop.tet != (tetrahedron *) NULL) {
28981 if (elemattribute(tetloop.tet, attrnum) == -1.0) {
28982 tetloop.tet = tetrahedrontraverse();
28988 for (i = 0; i < 4; i++) p[i] = (point) tetloop.tet[4 + i];
28991 tetvol = orient3dfast(p[1], p[0], p[2], p[3]) / 6.0;
28992 total_tet_vol += tetvol;
28993 total_tetprism_vol += tetprismvol(p[0], p[1], p[2], p[3]);
28996 if (tetvol < smallestvolume) {
28997 smallestvolume = tetvol;
28999 if (tetvol > biggestvolume) {
29000 biggestvolume = tetvol;
29004 for (i = 0; i < 3; i++) V[0][i] = p[0][i] - p[3][i];
29005 for (i = 0; i < 3; i++) V[1][i] = p[1][i] - p[3][i];
29006 for (i = 0; i < 3; i++) V[2][i] = p[2][i] - p[3][i];
29007 for (i = 0; i < 3; i++) V[3][i] = p[1][i] - p[0][i];
29008 for (i = 0; i < 3; i++) V[4][i] = p[2][i] - p[1][i];
29009 for (i = 0; i < 3; i++) V[5][i] = p[0][i] - p[2][i];
29012 for (i = 0; i < 6; i++) edgelength[i] = dot(V[i], V[i]);
29015 for (i = 0; i < 6; i++) {
29017 shortlen = longlen = edgelength[i];
29019 shortlen = edgelength[i] < shortlen ? edgelength[i] : shortlen;
29020 longlen = edgelength[i] > longlen ? edgelength[i] : longlen;
29022 if (edgelength[i] > longest) {
29023 longest = edgelength[i];
29025 if (edgelength[i] < shortest) {
29026 shortest = edgelength[i];
29031 for (j = 0; j < 3; j++) {
29032 for (i = 0; i < 3; i++) A[j][i] = V[j][i];
29036 if (lu_decmp(A, 3, indx, &D, 0)) {
29038 for (j = 0; j < 3; j++) {
29039 for (i = 0; i < 3; i++) rhs[i] = 0.0;
29041 lu_solve(A, 3, indx, rhs, 0);
29042 for (i = 0; i < 3; i++) N[j][i] = rhs[i];
29045 for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
29047 for (i = 0; i < 3; i++) rhs[i] = 0.5 * dot(V[i], V[i]);
29048 lu_solve(A, 3, indx, rhs, 0);
29049 cirradius = sqrt(dot(rhs, rhs));
29051 for (i = 0; i < 4; i++) {
29053 H[i] = sqrt(dot(N[i], N[i]));
29054 for (j = 0; j < 3; j++) N[i][j] /= H[i];
29059 minheightinv = H[0];
29060 for (i = 1; i < 4; i++) {
29061 if (H[i] > minheightinv) minheightinv = H[i];
29065 if (tetvol <= 0.0) {
29066 printf(
" !! Warning: A %s tet (%d,%d,%d,%d).\n",
29067 tetvol < 0 ?
"inverted" :
"degenerated", pointmark(p[0]),
29068 pointmark(p[1]), pointmark(p[2]), pointmark(p[3]));
29070 tetloop.tet = tetrahedrontraverse();
29074 facenormal(p[2], p[1], p[3], N[0], 1, NULL);
29075 facenormal(p[0], p[2], p[3], N[1], 1, NULL);
29076 facenormal(p[1], p[0], p[3], N[2], 1, NULL);
29077 facenormal(p[0], p[1], p[2], N[3], 1, NULL);
29079 for (i = 0; i < 4; i++) {
29081 H[i] = sqrt(dot(N[i], N[i]));
29082 for (j = 0; j < 3; j++) N[i][j] /= H[i];
29085 minheightinv = (H[0] / tetvol);
29086 for (i = 1; i < 4; i++) {
29087 if ((H[i] / tetvol) > minheightinv) minheightinv = (H[i] / tetvol);
29090 cirradius = 0.5 * sqrt(longlen);
29095 for (i = 1; i < 4; i++) {
29096 alldihed[j] = -dot(N[0], N[i]);
29097 if (alldihed[j] < -1.0) alldihed[j] = -1;
29098 else if (alldihed[j] > 1.0) alldihed[j] = 1;
29099 alldihed[j] = acos(alldihed[j]) / PI * 180.0;
29102 for (i = 2; i < 4; i++) {
29103 alldihed[j] = -dot(N[1], N[i]);
29104 if (alldihed[j] < -1.0) alldihed[j] = -1;
29105 else if (alldihed[j] > 1.0) alldihed[j] = 1;
29106 alldihed[j] = acos(alldihed[j]) / PI * 180.0;
29109 alldihed[j] = -dot(N[2], N[3]);
29110 if (alldihed[j] < -1.0) alldihed[j] = -1;
29111 else if (alldihed[j] > 1.0) alldihed[j] = 1;
29112 alldihed[j] = acos(alldihed[j]) / PI * 180.0;
29115 for (i = 0; i < 6; i++) {
29117 smalldiangle = bigdiangle = alldihed[i];
29119 smalldiangle = alldihed[i] < smalldiangle ? alldihed[i] : smalldiangle;
29120 bigdiangle = alldihed[i] > bigdiangle ? alldihed[i] : bigdiangle;
29122 if (alldihed[i] < smallestdiangle) {
29123 smallestdiangle = alldihed[i];
29125 if (alldihed[i] > biggestdiangle) {
29126 biggestdiangle = alldihed[i];
29129 if (alldihed[i] < 5.0) {
29131 }
else if (alldihed[i] >= 5.0 && alldihed[i] < 10.0) {
29133 }
else if (alldihed[i] >= 80.0 && alldihed[i] < 110.0) {
29135 }
else if (alldihed[i] >= 170.0 && alldihed[i] < 175.0) {
29137 }
else if (alldihed[i] >= 175.0) {
29140 tendegree = (int) (alldihed[i] / 10.);
29141 if (alldihed[i] < 80.0) {
29147 dihedangletable[tendegree]++;
29153 for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
29154 fsym(tetloop, neightet);
29156 if (((point) neightet.tet[7] == dummypoint) ||
29157 (tetloop.tet < neightet.tet)) {
29158 p[0] = org(tetloop);
29159 p[1] = dest(tetloop);
29160 p[2] = apex(tetloop);
29161 faceangle[0] = interiorangle(p[0], p[1], p[2], NULL);
29162 faceangle[1] = interiorangle(p[1], p[2], p[0], NULL);
29163 faceangle[2] = PI - (faceangle[0] + faceangle[1]);
29165 for (i = 0; i < 3; i++) {
29166 faceangle[i] = (faceangle[i] * 180.0) / PI;
29169 for (i = 0; i < 3; i++) {
29171 smallfaangle = bigfaangle = faceangle[i];
29173 smallfaangle = faceangle[i] < smallfaangle ?
29174 faceangle[i] : smallfaangle;
29175 bigfaangle = faceangle[i] > bigfaangle ? faceangle[i] : bigfaangle;
29177 if (faceangle[i] < smallestfaangle) {
29178 smallestfaangle = faceangle[i];
29180 if (faceangle[i] > biggestfaangle) {
29181 biggestfaangle = faceangle[i];
29183 tendegree = (int) (faceangle[i] / 10.);
29184 faceangletable[tendegree]++;
29190 tetradius = cirradius / sqrt(shortlen);
29191 if (tetradius < smallestradiusratio) {
29192 smallestradiusratio = tetradius;
29194 if (tetradius > biggestradiusratio) {
29195 biggestradiusratio = tetradius;
29196 biggestradiusratiotet.tet = tetloop.tet;
29199 tetaspect = sqrt(longlen) * minheightinv;
29201 if (tetaspect < smallestratio) {
29202 smallestratio = tetaspect;
29204 if (tetaspect > biggestratio) {
29205 biggestratio = tetaspect;
29209 while ((tetaspect > aspectratiotable[aspectindex]) && (aspectindex < 11)) {
29212 aspecttable[aspectindex]++;
29214 while ((tetradius > radiusratiotable[radiusindex]) && (radiusindex < 11)) {
29217 radiustable[radiusindex]++;
29219 tetloop.tet = tetrahedrontraverse();
29222 shortest = sqrt(shortest);
29223 longest = sqrt(longest);
29224 minaltitude = sqrt(minaltitude);
29226 printf(
" Smallest volume: %16.5g | Largest volume: %16.5g\n",
29227 smallestvolume, biggestvolume);
29228 printf(
" Shortest edge: %16.5g | Longest edge: %16.5g\n",
29229 shortest, longest);
29230 printf(
" Smallest asp.ratio: %13.5g | Largest asp.ratio: %13.5g\n",
29231 smallestratio, biggestratio);
29232 sprintf(sbuf,
"%.17g", biggestfaangle);
29233 if (strlen(sbuf) > 8) {
29236 printf(
" Smallest facangle: %14.5g | Largest facangle: %s\n",
29237 smallestfaangle, sbuf);
29238 sprintf(sbuf,
"%.17g", biggestdiangle);
29239 if (strlen(sbuf) > 8) {
29242 printf(
" Smallest dihedral: %14.5g | Largest dihedral: %s\n\n",
29243 smallestdiangle, sbuf);
29245 printf(
" Aspect ratio histogram:\n");
29246 printf(
" < %-6.6g : %8ld | %6.6g - %-6.6g : %8ld\n",
29247 aspectratiotable[0], aspecttable[0], aspectratiotable[5],
29248 aspectratiotable[6], aspecttable[6]);
29249 for (i = 1; i < 5; i++) {
29250 printf(
" %6.6g - %-6.6g : %8ld | %6.6g - %-6.6g : %8ld\n",
29251 aspectratiotable[i - 1], aspectratiotable[i], aspecttable[i],
29252 aspectratiotable[i + 5], aspectratiotable[i + 6],
29253 aspecttable[i + 6]);
29255 printf(
" %6.6g - %-6.6g : %8ld | %6.6g - : %8ld\n",
29256 aspectratiotable[4], aspectratiotable[5], aspecttable[5],
29257 aspectratiotable[10], aspecttable[11]);
29258 printf(
" (A tetrahedron's aspect ratio is its longest edge length");
29259 printf(
" divided by its\n");
29260 printf(
" smallest side height)\n\n");
29262 printf(
" Face angle histogram:\n");
29263 for (i = 0; i < 9; i++) {
29264 printf(
" %3d - %3d degrees: %8ld | %3d - %3d degrees: %8ld\n",
29265 i * 10, i * 10 + 10, faceangletable[i],
29266 i * 10 + 90, i * 10 + 100, faceangletable[i + 9]);
29268 if (minfaceang != PI) {
29269 printf(
" Minimum input face angle is %g (degree).\n",
29270 minfaceang / PI * 180.0);
29274 printf(
" Dihedral angle histogram:\n");
29276 printf(
" %3d - %2d degrees: %8ld | %3d - %3d degrees: %8ld\n",
29277 0, 5, dihedangletable[0], 80, 110, dihedangletable[9]);
29278 printf(
" %3d - %2d degrees: %8ld | %3d - %3d degrees: %8ld\n",
29279 5, 10, dihedangletable[1], 110, 120, dihedangletable[10]);
29281 for (i = 2; i < 7; i++) {
29282 printf(
" %3d - %2d degrees: %8ld | %3d - %3d degrees: %8ld\n",
29283 (i - 1) * 10, (i - 1) * 10 + 10, dihedangletable[i],
29284 (i - 1) * 10 + 110, (i - 1) * 10 + 120, dihedangletable[i + 9]);
29287 printf(
" %3d - %2d degrees: %8ld | %3d - %3d degrees: %8ld\n",
29288 60, 70, dihedangletable[7], 170, 175, dihedangletable[16]);
29289 printf(
" %3d - %2d degrees: %8ld | %3d - %3d degrees: %8ld\n",
29290 70, 80, dihedangletable[8], 175, 180, dihedangletable[17]);
29291 if (minfacetdihed != PI) {
29292 printf(
" Minimum input dihedral angle is %g (degree).\n",
29293 minfacetdihed / PI * 180.0);
29307 void tetgenmesh::memorystatistics()
29309 printf(
"Memory usage statistics:\n\n");
29313 tetrahedrons->pathblock = tetrahedrons->firstblock;
29314 while (tetrahedrons->pathblock != NULL) {
29316 tetrahedrons->pathblock = (
void **) *(tetrahedrons->pathblock);
29320 unsigned long totalmeshmemory = 0l, totalt2shmemory = 0l;
29321 totalmeshmemory = points->maxitems * points->itembytes +
29322 tetrahedrons->maxitems * tetrahedrons->itembytes;
29323 if (b->plc || b->refine) {
29324 totalmeshmemory += (subfaces->maxitems * subfaces->itembytes +
29325 subsegs->maxitems * subsegs->itembytes);
29326 totalt2shmemory = (tet2subpool->maxitems * tet2subpool->itembytes +
29327 tet2segpool->maxitems * tet2segpool->itembytes);
29330 unsigned long totalalgomemory = 0l;
29331 totalalgomemory = cavetetlist->totalmemory + cavebdrylist->totalmemory +
29332 caveoldtetlist->totalmemory +
29333 flippool->maxitems * flippool->itembytes;
29334 if (b->plc || b->refine) {
29335 totalalgomemory += (subsegstack->totalmemory + subfacstack->totalmemory +
29336 subvertstack->totalmemory +
29337 caveshlist->totalmemory + caveshbdlist->totalmemory +
29338 cavesegshlist->totalmemory +
29339 cavetetshlist->totalmemory +
29340 cavetetseglist->totalmemory +
29341 caveencshlist->totalmemory +
29342 caveencseglist->totalmemory +
29343 cavetetvertlist->totalmemory +
29344 unflipqueue->totalmemory);
29347 printf(
" Maximum number of tetrahedra: %ld\n", tetrahedrons->maxitems);
29348 printf(
" Maximum number of tet blocks (blocksize = %d): %d\n",
29349 b->tetrahedraperblock, tetblocks);
29369 if (b->plc || b->refine) {
29370 printf(
" Approximate memory for tetrahedral mesh (bytes): ");
29371 printfcomma(totalmeshmemory); printf(
"\n");
29373 printf(
" Approximate memory for extra pointers (bytes): ");
29374 printfcomma(totalt2shmemory); printf(
"\n");
29376 printf(
" Approximate memory for tetrahedralization (bytes): ");
29377 printfcomma(totalmeshmemory); printf(
"\n");
29379 printf(
" Approximate memory for algorithms (bytes): ");
29380 printfcomma(totalalgomemory); printf(
"\n");
29381 printf(
" Approximate memory for working arrays (bytes): ");
29382 printfcomma(totalworkmemory); printf(
"\n");
29383 printf(
" Approximate total used memory (bytes): ");
29384 printfcomma(totalmeshmemory + totalt2shmemory + totalalgomemory +
29397 void tetgenmesh::statistics()
29399 long tetnumber, facenumber;
29401 printf(
"\nStatistics:\n\n");
29402 printf(
" Input points: %d\n", in->numberofpoints);
29404 printf(
" Input tetrahedra: %d\n", in->numberoftetrahedra);
29405 if (in->numberoftrifaces > 0) {
29406 printf(
" Input triangles: %d\n", in->numberoftrifaces);
29408 if (in->numberofedges > 0) {
29409 printf(
" Input edges: %d\n", in->numberofedges);
29411 }
else if (b->plc) {
29412 printf(
" Input facets: %d\n", in->numberoffacets);
29413 printf(
" Input segments: %ld\n", insegments);
29414 if (in->numberofedges > 0) {
29415 printf(
" Input edges: %d\n", in->numberofedges);
29417 printf(
" Input holes: %d\n", in->numberofholes);
29418 printf(
" Input regions: %d\n", in->numberofregions);
29421 tetnumber = tetrahedrons->items - hullsize;
29422 facenumber = (tetnumber * 4l + hullsize) / 2l;
29425 printf(
"\n Mesh points: %ld\n", points->items - nonregularcount);
29427 printf(
"\n Mesh points: %ld\n", points->items);
29429 printf(
" Mesh tetrahedra: %ld\n", tetnumber);
29430 printf(
" Mesh faces: %ld\n", facenumber);
29431 if (meshedges > 0l) {
29432 printf(
" Mesh edges: %ld\n", meshedges);
29435 long vsize = points->items - dupverts - unuverts;
29436 if (b->weighted) vsize -= nonregularcount;
29437 meshedges = vsize + facenumber - tetnumber - 1;
29438 printf(
" Mesh edges: %ld\n", meshedges);
29442 if (b->plc || b->refine) {
29443 printf(
" Mesh faces on exterior boundary: %ld\n", hullsize);
29444 if (meshhulledges > 0l) {
29445 printf(
" Mesh edges on exterior boundary: %ld\n", meshhulledges);
29447 printf(
" Mesh faces on input facets: %ld\n", subfaces->items);
29448 printf(
" Mesh edges on input segments: %ld\n", subsegs->items);
29449 if (st_facref_count > 0l) {
29450 printf(
" Steiner points on input facets: %ld\n", st_facref_count);
29452 if (st_segref_count > 0l) {
29453 printf(
" Steiner points on input segments: %ld\n", st_segref_count);
29455 if (st_volref_count > 0l) {
29456 printf(
" Steiner points inside domain: %ld\n", st_volref_count);
29459 printf(
" Convex hull faces: %ld\n", hullsize);
29460 if (meshhulledges > 0l) {
29461 printf(
" Convex hull edges: %ld\n", meshhulledges);
29465 printf(
" Skipped non-regular points: %ld\n", nonregularcount);
29470 if (b->verbose > 0) {
29471 if (b->plc || b->refine) {
29472 if (tetrahedrons->items > 0l) {
29473 qualitystatistics();
29476 if (tetrahedrons->items > 0l) {
29477 memorystatistics();
29502 void tetgenmesh::jettisonnodes()
29506 int oldidx, newidx;
29510 printf(
"Jettisoning redundant points.\n");
29513 points->traversalinit();
29514 pointloop = pointtraverse();
29515 oldidx = newidx = 0;
29517 while (pointloop != (point) NULL) {
29518 jetflag = (pointtype(pointloop) == DUPLICATEDVERTEX) ||
29519 (pointtype(pointloop) == UNUSEDVERTEX);
29522 pointdealloc(pointloop);
29526 setpointmark(pointloop, newidx + in->firstnumber);
29527 if (in->pointmarkerlist != (
int *) NULL) {
29528 if (oldidx < in->numberofpoints) {
29530 in->pointmarkerlist[newidx] = in->pointmarkerlist[oldidx];
29536 pointloop = pointtraverse();
29539 printf(
" %ld duplicated vertices are removed.\n", dupverts);
29540 printf(
" %ld unused vertices are removed.\n", unuverts);
29548 points->deaditemstack = (
void *) NULL;
29561 void tetgenmesh::highorder()
29563 triface tetloop, worktet, spintet;
29564 point *extralist, *adjextralist;
29565 point torg, tdest, newpoint;
29566 int highorderindex;
29571 printf(
"Adding vertices for second-order tetrahedra.\n");
29575 highordertable =
new point[tetrahedrons->items * 6];
29576 if (highordertable == (point *) NULL) {
29577 terminatetetgen(
this, 1);
29581 highorderindex = 11;
29588 points->deaditemstack = (
void *) NULL;
29593 tetrahedrons->traversalinit();
29594 tetloop.tet = tetrahedrontraverse();
29595 while (tetloop.tet != (tetrahedron *) NULL) {
29596 tetloop.tet[highorderindex] = (tetrahedron) &highordertable[i];
29597 for (j = 0; j < 6; j++) {
29598 highordertable[i + j] = (point) NULL;
29601 tetloop.tet = tetrahedrontraverse();
29609 tetrahedrons->traversalinit();
29610 tetloop.tet = tetrahedrontraverse();
29611 while (tetloop.tet != (tetrahedron *) NULL) {
29613 extralist = (point *) tetloop.tet[highorderindex];
29614 worktet.tet = tetloop.tet;
29615 for (i = 0; i < 6; i++) {
29616 if (extralist[i] == (point) NULL) {
29618 worktet.ver = edge2ver[i];
29620 torg = org(worktet);
29621 tdest = dest(worktet);
29622 makepoint(&newpoint, FREEVOLVERTEX);
29623 for (j = 0; j < 3 + numpointattrib; j++) {
29624 newpoint[j] = 0.5 * (torg[j] + tdest[j]);
29627 for (j = 0; j < in->numberofpointmtrs; j++) {
29628 newpoint[pointmtrindex + j] =
29629 0.5 * (torg[pointmtrindex + j] + tdest[pointmtrindex + j]);
29634 if (!ishulltet(spintet)) {
29635 adjextralist = (point *) spintet.tet[highorderindex];
29636 adjextralist[ver2edge[spintet.ver]] = newpoint;
29638 fnextself(spintet);
29639 if (spintet.tet == worktet.tet)
break;
29643 tetloop.tet = tetrahedrontraverse();
29656 void tetgenmesh::indexelements()
29659 int eindex = b->zeroindex ? 0 : in->firstnumber;
29660 tetrahedrons->traversalinit();
29661 worktet.tet = tetrahedrontraverse();
29662 while (worktet.tet != NULL) {
29663 setelemindex(worktet.tet, eindex);
29668 tetrahedron tptr = encode(worktet);
29669 for (
int i = 0; i < 4; i++) {
29670 setpoint2tet((point) (worktet.tet[4 + i]), tptr);
29673 worktet.tet = tetrahedrontraverse();
29689 void tetgenmesh::numberedges()
29691 triface worktet, spintet;
29696 meshedges = meshhulledges = 0l;
29698 tetrahedrons->traversalinit();
29699 worktet.tet = tetrahedrontraverse();
29700 while (worktet.tet != NULL) {
29701 for (i = 0; i < 6; i++) {
29702 worktet.ver = edge2ver[i];
29704 fnext(worktet, spintet);
29706 if (!ishulltet(spintet)) {
29707 if (elemindex(spintet.tet) < elemindex(worktet.tet))
break;
29711 fnextself(spintet);
29712 }
while (spintet.tet != worktet.tet);
29713 if (spintet.tet == worktet.tet) {
29715 if (ishulledge) meshhulledges++;
29719 worktet.tet = tetrahedrontraverse();
29732 void tetgenmesh::outnodes(
tetgenio* out)
29734 FILE *outfile = NULL;
29735 char outnodefilename[FILENAMESIZE];
29738 int nextras, bmark, marker = 0, weightDT = 0;
29739 int coordindex, attribindex;
29740 int pointnumber, firstindex;
29744 strcpy(outnodefilename, b->outfilename);
29745 strcat(outnodefilename,
".node");
29750 printf(
"Writing %s.\n", outnodefilename);
29752 printf(
"Writing nodes.\n");
29756 nextras = numpointattrib;
29758 if (b->weighted_param == 0) weightDT = 1;
29761 bmark = !b->nobound && in->pointmarkerlist;
29764 outfile = fopen(outnodefilename,
"w");
29765 if (outfile == (FILE *) NULL) {
29766 printf(
"File I/O Error: Cannot create file %s.\n", outnodefilename);
29767 terminatetetgen(
this, 1);
29771 fprintf(outfile,
"%ld %d %d %d\n", points->items, 3, nextras, bmark);
29774 out->pointlist =
new REAL[points->items * 3];
29775 if (out->pointlist == (REAL *) NULL) {
29776 printf(
"Error: Out of memory.\n");
29777 terminatetetgen(
this, 1);
29781 out->pointattributelist =
new REAL[points->items * nextras];
29782 if (out->pointattributelist == (REAL *) NULL) {
29783 printf(
"Error: Out of memory.\n");
29784 terminatetetgen(
this, 1);
29789 out->pointmarkerlist =
new int[points->items];
29790 if (out->pointmarkerlist == (
int *) NULL) {
29791 printf(
"Error: Out of memory.\n");
29792 terminatetetgen(
this, 1);
29797 if (out->pointparamlist == NULL) {
29798 printf(
"Error: Out of memory.\n");
29799 terminatetetgen(
this, 1);
29802 out->numberofpoints = points->items;
29803 out->numberofpointattributes = nextras;
29809 firstindex = b->zeroindex ? 0 : in->firstnumber;
29811 points->traversalinit();
29812 pointloop = pointtraverse();
29813 pointnumber = firstindex;
29815 while (pointloop != (point) NULL) {
29820 if (index < in->numberofpoints) {
29822 marker = in->pointmarkerlist[index];
29824 if ((pointtype(pointloop) == FREESEGVERTEX) ||
29825 (pointtype(pointloop) == FREEFACETVERTEX)) {
29826 sdecode(point2sh(pointloop), parentsh);
29827 if (parentsh.sh != NULL) {
29828 marker = shellmark(parentsh);
29835 fprintf(outfile,
"%4d %.17g %.17g %.17g", pointnumber,
29836 pointloop[0], pointloop[1], pointloop[2]);
29837 for (i = 0; i < nextras; i++) {
29839 if ((i == 0) && weightDT) {
29840 fprintf(outfile,
" %.17g", pointloop[0] * pointloop[0] +
29841 pointloop[1] * pointloop[1] + pointloop[2] * pointloop[2]
29842 - pointloop[3 + i]);
29844 fprintf(outfile,
" %.17g", pointloop[3 + i]);
29849 fprintf(outfile,
" %d", marker);
29852 fprintf(outfile,
" %.8g %.8g %d", pointgeomuv(pointloop, 0),
29853 pointgeomuv(pointloop, 1), pointgeomtag(pointloop));
29854 if (pointtype(pointloop) == RIDGEVERTEX) {
29855 fprintf(outfile,
" 0");
29856 }
else if (pointtype(pointloop) == ACUTEVERTEX) {
29857 fprintf(outfile,
" 0");
29858 }
else if (pointtype(pointloop) == FREESEGVERTEX) {
29859 fprintf(outfile,
" 1");
29860 }
else if (pointtype(pointloop) == FREEFACETVERTEX) {
29861 fprintf(outfile,
" 2");
29862 }
else if (pointtype(pointloop) == FREEVOLVERTEX) {
29863 fprintf(outfile,
" 3");
29865 fprintf(outfile,
" -1");
29868 fprintf(outfile,
"\n");
29871 out->pointlist[coordindex++] = pointloop[0];
29872 out->pointlist[coordindex++] = pointloop[1];
29873 out->pointlist[coordindex++] = pointloop[2];
29875 for (i = 0; i < nextras; i++) {
29877 if ((i == 0) && weightDT) {
29878 out->pointattributelist[attribindex++] =
29879 pointloop[0] * pointloop[0] + pointloop[1] * pointloop[1] +
29880 pointloop[2] * pointloop[2] - pointloop[3 + i];
29882 out->pointattributelist[attribindex++] = pointloop[3 + i];
29887 out->pointmarkerlist[index] = marker;
29890 out->pointparamlist[index].uv[0] = pointgeomuv(pointloop, 0);
29891 out->pointparamlist[index].uv[1] = pointgeomuv(pointloop, 1);
29892 out->pointparamlist[index].tag = pointgeomtag(pointloop);
29893 if (pointtype(pointloop) == RIDGEVERTEX) {
29894 out->pointparamlist[index].type = 0;
29895 }
else if (pointtype(pointloop) == ACUTEVERTEX) {
29896 out->pointparamlist[index].type = 0;
29897 }
else if (pointtype(pointloop) == FREESEGVERTEX) {
29898 out->pointparamlist[index].type = 1;
29899 }
else if (pointtype(pointloop) == FREEFACETVERTEX) {
29900 out->pointparamlist[index].type = 2;
29901 }
else if (pointtype(pointloop) == FREEVOLVERTEX) {
29902 out->pointparamlist[index].type = 3;
29904 out->pointparamlist[index].type = -1;
29908 pointloop = pointtraverse();
29914 fprintf(outfile,
"# Generated by %s\n", b->commandline);
29925 void tetgenmesh::outmetrics(
tetgenio* out)
29927 FILE *outfile = NULL;
29928 char outmtrfilename[FILENAMESIZE];
29932 int msize = (sizeoftensor - useinsertradius);
29938 strcpy(outmtrfilename, b->outfilename);
29939 strcat(outmtrfilename,
".mtr");
29944 printf(
"Writing %s.\n", outmtrfilename);
29946 printf(
"Writing metrics.\n");
29951 outfile = fopen(outmtrfilename,
"w");
29952 if (outfile == (FILE *) NULL) {
29953 printf(
"File I/O Error: Cannot create file %s.\n", outmtrfilename);
29954 terminatetetgen(
this, 3);
29957 fprintf(outfile,
"%ld %d\n", points->items, msize);
29960 out->numberofpointmtrs = msize;
29961 out->pointmtrlist =
new REAL[points->items * msize];
29962 if (out->pointmtrlist == (REAL *) NULL) {
29963 terminatetetgen(
this, 1);
29967 points->traversalinit();
29968 ptloop = pointtraverse();
29969 while (ptloop != (point) NULL) {
29971 for (i = 0; i < msize; i++) {
29972 fprintf(outfile,
" %-16.8e", ptloop[pointmtrindex + i]);
29974 fprintf(outfile,
"\n");
29976 for (i = 0; i < msize; i++) {
29977 out->pointmtrlist[mtrindex++] = ptloop[pointmtrindex + i];
29980 ptloop = pointtraverse();
29985 strcpy(outmtrfilename, b->outfilename);
29986 strcat(outmtrfilename,
".p2t");
29991 printf(
"Writing %s.\n", outmtrfilename);
29993 printf(
"Writing point-to-tet map.\n");
29998 outfile = fopen(outmtrfilename,
"w");
29999 if (outfile == (FILE *) NULL) {
30000 printf(
"File I/O Error: Cannot create file %s.\n", outmtrfilename);
30001 terminatetetgen(
this, 3);
30007 out->point2tetlist =
new int[points->items];
30008 if (out->point2tetlist == (
int *) NULL) {
30009 terminatetetgen(
this, 1);
30015 bgm->indexelements();
30018 int firstindex = b->zeroindex ? 0 : in->firstnumber;
30019 int pointindex = firstindex;
30023 points->traversalinit();
30024 ptloop = pointtraverse();
30025 while (ptloop != (point) NULL) {
30027 bgm->decode(point2bgmtet(ptloop), parenttet);
30029 decode(point2tet(ptloop), parenttet);
30032 fprintf(outfile,
"%d %d\n", pointindex, elemindex(parenttet.tet));
30034 out->point2tetlist[i] = elemindex(parenttet.tet);
30038 ptloop = pointtraverse();
30042 fprintf(outfile,
"# Generated by %s\n", b->commandline);
30057 void tetgenmesh::outelements(
tetgenio* out)
30059 FILE *outfile = NULL;
30060 char outelefilename[FILENAMESIZE];
30062 point p1, p2, p3, p4;
30064 REAL *talist = NULL;
30067 int firstindex, shift;
30068 int pointindex, attribindex;
30069 int highorderindex = 11;
30075 strcpy(outelefilename, b->outfilename);
30076 strcat(outelefilename,
".ele");
30081 printf(
"Writing %s.\n", outelefilename);
30083 printf(
"Writing elements.\n");
30088 ntets = tetrahedrons->items - hullsize;
30090 eextras = numelemattrib;
30092 outfile = fopen(outelefilename,
"w");
30093 if (outfile == (FILE *) NULL) {
30094 printf(
"File I/O Error: Cannot create file %s.\n", outelefilename);
30095 terminatetetgen(
this, 1);
30098 fprintf(outfile,
"%ld %d %d\n", ntets, b->order == 1 ? 4 : 10, eextras);
30101 out->tetrahedronlist =
new int[ntets * (b->order == 1 ? 4 : 10)];
30102 if (out->tetrahedronlist == (
int *) NULL) {
30103 printf(
"Error: Out of memory.\n");
30104 terminatetetgen(
this, 1);
30108 out->tetrahedronattributelist =
new REAL[ntets * eextras];
30109 if (out->tetrahedronattributelist == (REAL *) NULL) {
30110 printf(
"Error: Out of memory.\n");
30111 terminatetetgen(
this, 1);
30114 out->numberoftetrahedra = ntets;
30115 out->numberofcorners = b->order == 1 ? 4 : 10;
30116 out->numberoftetrahedronattributes = eextras;
30117 tlist = out->tetrahedronlist;
30118 talist = out->tetrahedronattributelist;
30124 firstindex = b->zeroindex ? 0 : in->firstnumber;
30126 if ((in->firstnumber == 1) && (firstindex == 0)) {
30130 tetrahedrons->traversalinit();
30131 tptr = tetrahedrontraverse();
30132 elementnumber = firstindex;
30133 while (tptr != (tetrahedron *) NULL) {
30134 if (!b->reversetetori) {
30135 p1 = (point) tptr[4];
30136 p2 = (point) tptr[5];
30138 p1 = (point) tptr[5];
30139 p2 = (point) tptr[4];
30141 p3 = (point) tptr[6];
30142 p4 = (point) tptr[7];
30145 fprintf(outfile,
"%5d %5d %5d %5d %5d", elementnumber,
30146 pointmark(p1) - shift, pointmark(p2) - shift,
30147 pointmark(p3) - shift, pointmark(p4) - shift);
30148 if (b->order == 2) {
30149 extralist = (point *) tptr[highorderindex];
30151 fprintf(outfile,
" %5d %5d %5d %5d %5d %5d",
30152 pointmark(extralist[0]) - shift, pointmark(extralist[1]) - shift,
30153 pointmark(extralist[2]) - shift, pointmark(extralist[3]) - shift,
30154 pointmark(extralist[4]) - shift, pointmark(extralist[5]) - shift);
30156 for (i = 0; i < eextras; i++) {
30157 fprintf(outfile,
" %.17g", elemattribute(tptr, i));
30159 fprintf(outfile,
"\n");
30161 tlist[pointindex++] = pointmark(p1) - shift;
30162 tlist[pointindex++] = pointmark(p2) - shift;
30163 tlist[pointindex++] = pointmark(p3) - shift;
30164 tlist[pointindex++] = pointmark(p4) - shift;
30165 if (b->order == 2) {
30166 extralist = (point *) tptr[highorderindex];
30167 tlist[pointindex++] = pointmark(extralist[0]) - shift;
30168 tlist[pointindex++] = pointmark(extralist[1]) - shift;
30169 tlist[pointindex++] = pointmark(extralist[2]) - shift;
30170 tlist[pointindex++] = pointmark(extralist[3]) - shift;
30171 tlist[pointindex++] = pointmark(extralist[4]) - shift;
30172 tlist[pointindex++] = pointmark(extralist[5]) - shift;
30174 for (i = 0; i < eextras; i++) {
30175 talist[attribindex++] = elemattribute(tptr, i);
30179 setelemindex(tptr, elementnumber);
30183 for (
int i = 0; i < 4; i++) {
30184 setpoint2tet((point) (tptr[4 + i]), (tetrahedron) tptr);
30187 tptr = tetrahedrontraverse();
30193 fprintf(outfile,
"# Generated by %s\n", b->commandline);
30204 void tetgenmesh::outfaces(
tetgenio* out)
30206 FILE *outfile = NULL;
30207 char facefilename[FILENAMESIZE];
30208 triface tface, tsymface;
30210 point torg, tdest, tapex;
30212 int *elist = NULL, *emlist = NULL;
30213 int neigh1 = 0, neigh2 = 0;
30215 int firstindex, shift;
30221 point *extralist, pp[3] = {0,0,0};
30222 int highorderindex = 11;
30223 int o2index = 0, i;
30226 int *tet2facelist = NULL;
30230 strcpy(facefilename, b->outfilename);
30231 strcat(facefilename,
".face");
30236 printf(
"Writing %s.\n", facefilename);
30238 printf(
"Writing faces.\n");
30242 ntets = tetrahedrons->items - hullsize;
30243 faces = (ntets * 4l + hullsize) / 2l;
30246 outfile = fopen(facefilename,
"w");
30247 if (outfile == (FILE *) NULL) {
30248 printf(
"File I/O Error: Cannot create file %s.\n", facefilename);
30249 terminatetetgen(
this, 1);
30251 fprintf(outfile,
"%ld %d\n", faces, !b->nobound);
30254 out->trifacelist =
new int[faces * 3];
30255 if (out->trifacelist == (
int *) NULL) {
30256 printf(
"Error: Out of memory.\n");
30257 terminatetetgen(
this, 1);
30259 if (b->order == 2) {
30260 out->o2facelist =
new int[faces * 3];
30264 out->trifacemarkerlist =
new int[faces];
30265 if (out->trifacemarkerlist == (
int *) NULL) {
30266 printf(
"Error: Out of memory.\n");
30267 terminatetetgen(
this, 1);
30270 if (b->neighout > 1) {
30272 out->face2tetlist =
new int[faces * 2];
30273 if (out->face2tetlist == (
int *) NULL) {
30274 printf(
"Error: Out of memory.\n");
30275 terminatetetgen(
this, 1);
30278 out->numberoftrifaces = faces;
30279 elist = out->trifacelist;
30280 emlist = out->trifacemarkerlist;
30283 if (b->neighout > 1) {
30285 tet2facelist =
new int[ntets * 4];
30289 firstindex = b->zeroindex ? 0 : in->firstnumber;
30291 if ((in->firstnumber == 1) && (firstindex == 0)) {
30295 tetrahedrons->traversalinit();
30296 tface.tet = tetrahedrontraverse();
30297 facenumber = firstindex;
30302 while (tface.tet != (tetrahedron *) NULL) {
30303 for (tface.ver = 0; tface.ver < 4; tface.ver ++) {
30304 fsym(tface, tsymface);
30305 if (ishulltet(tsymface) ||
30306 (elemindex(tface.tet) < elemindex(tsymface.tet))) {
30308 tdest = dest(tface);
30309 tapex = apex(tface);
30310 if (b->order == 2) {
30312 extralist = (point *) (tface.tet[highorderindex]);
30314 enext(tface, workface);
30315 for (i = 0; i < 3; i++) {
30316 pp[i] = extralist[ver2edge[workface.ver]];
30317 enextself(workface);
30322 if (b->plc || b->refine) {
30324 tspivot(tface, checkmark);
30325 if (checkmark.sh == NULL) {
30328 marker = shellmark(checkmark);
30332 marker = (int) ishulltet(tsymface);
30335 if (b->neighout > 1) {
30337 if (!ishulltet(tface)) {
30338 neigh1 = elemindex(tface.tet);
30342 if (!ishulltet(tsymface)) {
30343 neigh2 = elemindex(tsymface.tet);
30348 tidx = elemindex(tface.tet) - firstindex;
30349 tet2facelist[tidx * 4 + tface.ver] = facenumber;
30350 if (!ishulltet(tsymface)) {
30351 tidx = elemindex(tsymface.tet) - firstindex;
30352 tet2facelist[tidx * 4 + (tsymface.ver & 3)] = facenumber;
30357 fprintf(outfile,
"%5d %4d %4d %4d", facenumber,
30358 pointmark(torg) - shift, pointmark(tdest) - shift,
30359 pointmark(tapex) - shift);
30360 if (b->order == 2) {
30361 fprintf(outfile,
" %4d %4d %4d", pointmark(pp[0]) - shift,
30362 pointmark(pp[1]) - shift, pointmark(pp[2]) - shift);
30366 fprintf(outfile,
" %d", marker);
30368 if (b->neighout > 1) {
30369 fprintf(outfile,
" %5d %5d", neigh1, neigh2);
30371 fprintf(outfile,
"\n");
30374 elist[index++] = pointmark(torg) - shift;
30375 elist[index++] = pointmark(tdest) - shift;
30376 elist[index++] = pointmark(tapex) - shift;
30377 if (b->order == 2) {
30378 out->o2facelist[o2index++] = pointmark(pp[0]) - shift;
30379 out->o2facelist[o2index++] = pointmark(pp[1]) - shift;
30380 out->o2facelist[o2index++] = pointmark(pp[2]) - shift;
30383 emlist[facenumber - in->firstnumber] = marker;
30385 if (b->neighout > 1) {
30386 out->face2tetlist[(facenumber - in->firstnumber) * 2] = neigh1;
30387 out->face2tetlist[(facenumber - in->firstnumber) * 2 + 1] = neigh2;
30393 tface.tet = tetrahedrontraverse();
30397 fprintf(outfile,
"# Generated by %s\n", b->commandline);
30401 if (b->neighout > 1) {
30404 strcpy(facefilename, b->outfilename);
30405 strcat(facefilename,
".t2f");
30409 printf(
"Writing %s.\n", facefilename);
30411 printf(
"Writing tetrahedron-to-face map.\n");
30415 outfile = fopen(facefilename,
"w");
30416 for (tidx = 0; tidx < ntets; tidx++) {
30418 fprintf(outfile,
"%4d %d %d %d %d\n", tidx + in->firstnumber,
30419 tet2facelist[index], tet2facelist[index+1],
30420 tet2facelist[index+2], tet2facelist[index+3]);
30423 delete [] tet2facelist;
30426 out->tet2facelist = tet2facelist;
30439 void tetgenmesh::outhullfaces(
tetgenio* out)
30441 FILE *outfile = NULL;
30442 char facefilename[FILENAMESIZE];
30444 point torg, tdest, tapex;
30446 int firstindex, shift;
30451 strcpy(facefilename, b->outfilename);
30452 strcat(facefilename,
".face");
30457 printf(
"Writing %s.\n", facefilename);
30459 printf(
"Writing faces.\n");
30464 outfile = fopen(facefilename,
"w");
30465 if (outfile == (FILE *) NULL) {
30466 printf(
"File I/O Error: Cannot create file %s.\n", facefilename);
30467 terminatetetgen(
this, 1);
30469 fprintf(outfile,
"%ld 0\n", hullsize);
30472 out->trifacelist =
new int[hullsize * 3];
30473 if (out->trifacelist == (
int *) NULL) {
30474 printf(
"Error: Out of memory.\n");
30475 terminatetetgen(
this, 1);
30477 out->numberoftrifaces = hullsize;
30478 elist = out->trifacelist;
30483 firstindex = b->zeroindex ? 0 : in->firstnumber;
30485 if ((in->firstnumber == 1) && (firstindex == 0)) {
30489 tetrahedrons->traversalinit();
30490 hulltet.tet = alltetrahedrontraverse();
30491 facenumber = firstindex;
30492 while (hulltet.tet != (tetrahedron *) NULL) {
30493 if (ishulltet(hulltet)) {
30494 torg = (point) hulltet.tet[4];
30495 tdest = (point) hulltet.tet[5];
30496 tapex = (point) hulltet.tet[6];
30499 fprintf(outfile,
"%5d %4d %4d %4d", facenumber,
30500 pointmark(torg) - shift, pointmark(tdest) - shift,
30501 pointmark(tapex) - shift);
30502 fprintf(outfile,
"\n");
30505 elist[index++] = pointmark(torg) - shift;
30506 elist[index++] = pointmark(tdest) - shift;
30507 elist[index++] = pointmark(tapex) - shift;
30511 hulltet.tet = alltetrahedrontraverse();
30515 fprintf(outfile,
"# Generated by %s\n", b->commandline);
30531 void tetgenmesh::outsubfaces(
tetgenio* out)
30533 FILE *outfile = NULL;
30534 char facefilename[FILENAMESIZE];
30536 int *emlist = NULL;
30537 int index = 0, index1 = 0, index2 = 0;
30538 triface abuttingtet;
30540 point torg, tdest, tapex;
30542 int firstindex, shift;
30543 int neigh1 = 0, neigh2 = 0;
30548 point *extralist, pp[3] = {0,0,0};
30549 int highorderindex = 11;
30550 int o2index = 0, i;
30555 strcpy(facefilename, b->outfilename);
30556 strcat(facefilename,
".face");
30561 printf(
"Writing %s.\n", facefilename);
30563 printf(
"Writing faces.\n");
30568 outfile = fopen(facefilename,
"w");
30569 if (outfile == (FILE *) NULL) {
30570 printf(
"File I/O Error: Cannot create file %s.\n", facefilename);
30571 terminatetetgen(
this, 3);
30574 fprintf(outfile,
"%ld %d\n", subfaces->items, !b->nobound);
30577 out->trifacelist =
new int[subfaces->items * 3];
30578 if (out->trifacelist == (
int *) NULL) {
30579 terminatetetgen(
this, 1);
30581 if (b->order == 2) {
30582 out->o2facelist =
new int[subfaces->items * 3];
30586 out->trifacemarkerlist =
new int[subfaces->items];
30587 if (out->trifacemarkerlist == (
int *) NULL) {
30588 terminatetetgen(
this, 1);
30591 if (b->neighout > 1) {
30593 out->face2tetlist =
new int[subfaces->items * 2];
30594 if (out->face2tetlist == (
int *) NULL) {
30595 terminatetetgen(
this, 1);
30598 out->numberoftrifaces = subfaces->items;
30599 elist = out->trifacelist;
30600 emlist = out->trifacemarkerlist;
30604 firstindex = b->zeroindex ? 0 : in->firstnumber;
30606 if ((in->firstnumber == 1) && (firstindex == 0)) {
30610 subfaces->traversalinit();
30611 faceloop.sh = shellfacetraverse(subfaces);
30612 facenumber = firstindex;
30613 while (faceloop.sh != (shellface *) NULL) {
30614 stpivot(faceloop, abuttingtet);
30618 if (abuttingtet.tet != NULL) {
30619 if (ishulltet(abuttingtet)) {
30620 fsymself(abuttingtet);
30623 if (abuttingtet.tet != NULL) {
30624 torg = org(abuttingtet);
30625 tdest = dest(abuttingtet);
30626 tapex = apex(abuttingtet);
30627 if (b->order == 2) {
30629 extralist = (point *) (abuttingtet.tet[highorderindex]);
30630 workface = abuttingtet;
30631 for (i = 0; i < 3; i++) {
30632 pp[i] = extralist[ver2edge[workface.ver]];
30633 enextself(workface);
30638 torg = sorg(faceloop);
30639 tdest = sdest(faceloop);
30640 tapex = sapex(faceloop);
30641 if (b->order == 2) {
30649 marker = shellmark(faceloop);
30651 if (b->neighout > 1) {
30655 stpivot(faceloop, abuttingtet);
30656 if (abuttingtet.tet != NULL) {
30657 if (!ishulltet(abuttingtet)) {
30658 neigh1 = elemindex(abuttingtet.tet);
30660 fsymself(abuttingtet);
30661 if (!ishulltet(abuttingtet)) {
30662 neigh2 = elemindex(abuttingtet.tet);
30667 fprintf(outfile,
"%5d %4d %4d %4d", facenumber,
30668 pointmark(torg) - shift, pointmark(tdest) - shift,
30669 pointmark(tapex) - shift);
30670 if (b->order == 2) {
30671 fprintf(outfile,
" %4d %4d %4d", pointmark(pp[0]) - shift,
30672 pointmark(pp[1]) - shift, pointmark(pp[2]) - shift);
30675 fprintf(outfile,
" %d", marker);
30677 if (b->neighout > 1) {
30678 fprintf(outfile,
" %5d %5d", neigh1, neigh2);
30680 fprintf(outfile,
"\n");
30683 elist[index++] = pointmark(torg) - shift;
30684 elist[index++] = pointmark(tdest) - shift;
30685 elist[index++] = pointmark(tapex) - shift;
30686 if (b->order == 2) {
30687 out->o2facelist[o2index++] = pointmark(pp[0]) - shift;
30688 out->o2facelist[o2index++] = pointmark(pp[1]) - shift;
30689 out->o2facelist[o2index++] = pointmark(pp[2]) - shift;
30692 emlist[index1++] = marker;
30694 if (b->neighout > 1) {
30695 out->face2tetlist[index2++] = neigh1;
30696 out->face2tetlist[index2++] = neigh2;
30700 faceloop.sh = shellfacetraverse(subfaces);
30704 fprintf(outfile,
"# Generated by %s\n", b->commandline);
30718 void tetgenmesh::outedges(
tetgenio* out)
30720 FILE *outfile = NULL;
30721 char edgefilename[FILENAMESIZE];
30722 triface tetloop, worktet, spintet;
30726 int firstindex, shift;
30727 int edgenumber, marker;
30728 int index = 0, index1 = 0, index2 = 0;
30733 point *extralist, pp = NULL;
30734 int highorderindex = 11;
30738 int *tet2edgelist = NULL;
30742 strcpy(edgefilename, b->outfilename);
30743 strcat(edgefilename,
".edge");
30748 printf(
"Writing %s.\n", edgefilename);
30750 printf(
"Writing edges.\n");
30754 if (meshedges == 0l) {
30760 long tsize = tetrahedrons->items - hullsize;
30761 long fsize = (tsize * 4l + hullsize) / 2l;
30762 long vsize = points->items - dupverts - unuverts;
30763 if (b->weighted) vsize -= nonregularcount;
30764 meshedges = vsize + fsize - tsize - 1;
30767 meshhulledges = 0l;
30770 outfile = fopen(edgefilename,
"w");
30771 if (outfile == (FILE *) NULL) {
30772 printf(
"File I/O Error: Cannot create file %s.\n", edgefilename);
30773 terminatetetgen(
this, 1);
30776 fprintf(outfile,
"%ld %d\n", meshedges, !b->nobound);
30779 out->numberofedges = meshedges;
30780 out->edgelist =
new int[meshedges * 2];
30781 if (out->edgelist == (
int *) NULL) {
30782 printf(
"Error: Out of memory.\n");
30783 terminatetetgen(
this, 1);
30785 if (b->order == 2) {
30786 out->o2edgelist =
new int[meshedges];
30789 out->edgemarkerlist =
new int[meshedges];
30791 if (b->neighout > 1) {
30792 out->edge2tetlist =
new int[meshedges];
30796 if (b->neighout > 1) {
30798 long tsize = tetrahedrons->items - hullsize;
30799 tet2edgelist =
new int[tsize * 6];
30803 firstindex = b->zeroindex ? 0 : in->firstnumber;
30805 if ((in->firstnumber == 1) && (firstindex == 0)) {
30809 tetrahedrons->traversalinit();
30810 tetloop.tet = tetrahedrontraverse();
30811 edgenumber = firstindex;
30812 while (tetloop.tet != (tetrahedron *) NULL) {
30814 worktet.tet = tetloop.tet;
30815 for (i = 0; i < 6; i++) {
30816 worktet.ver = edge2ver[i];
30818 fnext(worktet, spintet);
30820 if (!ishulltet(spintet)) {
30821 if (elemindex(spintet.tet) < elemindex(worktet.tet))
break;
30825 fnextself(spintet);
30826 }
while (spintet.tet != worktet.tet);
30827 if (spintet.tet == worktet.tet) {
30829 if (ishulledge) meshhulledges++;
30830 torg = org(worktet);
30831 tdest = dest(worktet);
30832 if (b->order == 2) {
30834 extralist = (point *) worktet.tet[highorderindex];
30835 pp = extralist[ver2edge[worktet.ver]];
30838 fprintf(outfile,
"%5d %4d %4d", edgenumber,
30839 pointmark(torg) - shift, pointmark(tdest) - shift);
30840 if (b->order == 2) {
30841 fprintf(outfile,
" %4d", pointmark(pp) - shift);
30845 out->edgelist[index++] = pointmark(torg) - shift;
30846 out->edgelist[index++] = pointmark(tdest) - shift;
30847 if (b->order == 2) {
30848 out->o2edgelist[o2index++] = pointmark(pp) - shift;
30852 if (b->plc || b->refine) {
30854 tsspivot1(worktet, checkseg);
30855 if (checkseg.sh != NULL) {
30856 marker = shellmark(checkseg);
30862 marker = ishulledge ? 1 : 0;
30865 fprintf(outfile,
" %d", marker);
30867 out->edgemarkerlist[index1++] = marker;
30870 if (b->neighout > 1) {
30872 fprintf(outfile,
" %d", elemindex(tetloop.tet));
30874 out->edge2tetlist[index2++] = elemindex(tetloop.tet);
30879 if (!ishulltet(spintet)) {
30880 tidx = elemindex(spintet.tet) - firstindex;
30881 tet2edgelist[tidx * 6 + ver2edge[spintet.ver]] = edgenumber;
30883 fnextself(spintet);
30884 if (spintet.tet == worktet.tet)
break;
30888 fprintf(outfile,
"\n");
30893 tetloop.tet = tetrahedrontraverse();
30897 fprintf(outfile,
"# Generated by %s\n", b->commandline);
30901 if (b->neighout > 1) {
30902 long tsize = tetrahedrons->items - hullsize;
30906 long fsize = (tsize * 4l + hullsize) / 2l;
30907 int *face2edgelist =
new int[fsize * 3];
30909 tetrahedrons->traversalinit();
30910 tetloop.tet = tetrahedrontraverse();
30911 int facenumber = 0;
30912 while (tetloop.tet != (tetrahedron *) NULL) {
30913 for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
30914 fsym(tetloop, spintet);
30915 if (ishulltet(spintet) ||
30916 (elemindex(tetloop.tet) < elemindex(spintet.tet))) {
30920 tidx = elemindex(tetloop.tet) - firstindex;
30922 for (i = 0; i < 3; i++) {
30923 enextself(worktet);
30924 int eidx = tet2edgelist[tidx * 6 + ver2edge[worktet.ver]];
30925 face2edgelist[facenumber * 3 + i] = eidx;
30930 tetloop.tet = tetrahedrontraverse();
30935 strcpy(edgefilename, b->outfilename);
30936 strcat(edgefilename,
".f2e");
30940 printf(
"Writing %s.\n", edgefilename);
30942 printf(
"Writing face-to-edge map.\n");
30946 outfile = fopen(edgefilename,
"w");
30947 for (tidx = 0; tidx < fsize; tidx++) {
30949 fprintf(outfile,
"%4d %d %d %d\n", tidx + in->firstnumber,
30950 face2edgelist[i], face2edgelist[i+1], face2edgelist[i+2]);
30953 delete [] face2edgelist;
30956 out->face2edgelist = face2edgelist;
30962 strcpy(edgefilename, b->outfilename);
30963 strcat(edgefilename,
".t2e");
30967 printf(
"Writing %s.\n", edgefilename);
30969 printf(
"Writing tetrahedron-to-edge map.\n");
30973 outfile = fopen(edgefilename,
"w");
30974 for (tidx = 0; tidx < tsize; tidx++) {
30976 fprintf(outfile,
"%4d %d %d %d %d %d %d\n", tidx + in->firstnumber,
30977 tet2edgelist[i], tet2edgelist[i+1], tet2edgelist[i+2],
30978 tet2edgelist[i+3], tet2edgelist[i+4], tet2edgelist[i+5]);
30981 delete [] tet2edgelist;
30984 out->tet2edgelist = tet2edgelist;
30995 void tetgenmesh::outsubsegments(
tetgenio* out)
30997 FILE *outfile = NULL;
30998 char edgefilename[FILENAMESIZE];
31003 int firstindex, shift;
31008 triface workface, spintet;
31009 point *extralist, pp = NULL;
31010 int highorderindex = 11;
31020 strcpy(edgefilename, b->outfilename);
31021 strcat(edgefilename,
".edge");
31026 printf(
"Writing %s.\n", edgefilename);
31028 printf(
"Writing edges.\n");
31033 outfile = fopen(edgefilename,
"w");
31034 if (outfile == (FILE *) NULL) {
31035 printf(
"File I/O Error: Cannot create file %s.\n", edgefilename);
31036 terminatetetgen(
this, 3);
31039 fprintf(outfile,
"%ld 1\n", subsegs->items);
31042 out->edgelist =
new int[subsegs->items * (b->order == 1 ? 2 : 3)];
31043 if (out->edgelist == (
int *) NULL) {
31044 terminatetetgen(
this, 1);
31046 if (b->order == 2) {
31047 out->o2edgelist =
new int[subsegs->items];
31049 out->edgemarkerlist =
new int[subsegs->items];
31050 if (out->edgemarkerlist == (
int *) NULL) {
31051 terminatetetgen(
this, 1);
31053 if (b->neighout > 1) {
31054 out->edge2tetlist =
new int[subsegs->items];
31056 out->numberofedges = subsegs->items;
31057 elist = out->edgelist;
31061 firstindex = b->zeroindex ? 0 : in->firstnumber;
31063 if ((in->firstnumber == 1) && (firstindex == 0)) {
31069 subsegs->traversalinit();
31070 edgeloop.sh = shellfacetraverse(subsegs);
31071 edgenumber = firstindex;
31072 while (edgeloop.sh != (shellface *) NULL) {
31073 torg = sorg(edgeloop);
31074 tdest = sdest(edgeloop);
31075 if ((b->order == 2) || (b->neighout > 1)) {
31076 sstpivot1(edgeloop, workface);
31077 if (workface.tet != NULL) {
31079 if (ishulltet(workface)) {
31080 spintet = workface;
31082 fnextself(spintet);
31083 if (!ishulltet(spintet))
break;
31084 if (spintet.tet == workface.tet)
break;
31086 workface = spintet;
31090 if (b->order == 2) {
31092 if (workface.tet != NULL) {
31093 extralist = (point *) workface.tet[highorderindex];
31094 pp = extralist[ver2edge[workface.ver]];
31099 if (b->neighout > 1) {
31100 if (workface.tet != NULL) {
31101 neigh = elemindex(workface.tet);
31106 marker = shellmark(edgeloop);
31111 fprintf(outfile,
"%5d %4d %4d", edgenumber,
31112 pointmark(torg) - shift, pointmark(tdest) - shift);
31113 if (b->order == 2) {
31114 fprintf(outfile,
" %4d", pointmark(pp) - shift);
31116 fprintf(outfile,
" %d", marker);
31117 if (b->neighout > 1) {
31118 fprintf(outfile,
" %4d", neigh);
31120 fprintf(outfile,
"\n");
31123 elist[index++] = pointmark(torg) - shift;
31124 elist[index++] = pointmark(tdest) - shift;
31125 if (b->order == 2) {
31126 out->o2edgelist[o2index++] = pointmark(pp) - shift;
31128 out->edgemarkerlist[i++] = marker;
31129 if (b->neighout > 1) {
31130 out->edge2tetlist[index2++] = neigh;
31134 edgeloop.sh = shellfacetraverse(subsegs);
31138 fprintf(outfile,
"# Generated by %s\n", b->commandline);
31149 void tetgenmesh::outneighbors(
tetgenio* out)
31151 FILE *outfile = NULL;
31152 char neighborfilename[FILENAMESIZE];
31155 triface tetloop, tetsym;
31162 strcpy(neighborfilename, b->outfilename);
31163 strcat(neighborfilename,
".neigh");
31168 printf(
"Writing %s.\n", neighborfilename);
31170 printf(
"Writing neighbors.\n");
31174 ntets = tetrahedrons->items - hullsize;
31177 outfile = fopen(neighborfilename,
"w");
31178 if (outfile == (FILE *) NULL) {
31179 printf(
"File I/O Error: Cannot create file %s.\n", neighborfilename);
31180 terminatetetgen(
this, 1);
31183 fprintf(outfile,
"%ld %d\n", ntets, 4);
31186 out->neighborlist =
new int[ntets * 4];
31187 if (out->neighborlist == (
int *) NULL) {
31188 printf(
"Error: Out of memory.\n");
31189 terminatetetgen(
this, 1);
31191 nlist = out->neighborlist;
31195 firstindex = b->zeroindex ? 0 : in->firstnumber;
31197 tetrahedrons->traversalinit();
31198 tetloop.tet = tetrahedrontraverse();
31199 elementnumber = firstindex;
31200 while (tetloop.tet != (tetrahedron *) NULL) {
31201 for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
31202 fsym(tetloop, tetsym);
31203 if (!ishulltet(tetsym)) {
31204 neighbori[tetloop.ver] = elemindex(tetsym.tet);
31206 neighbori[tetloop.ver] = -1;
31211 fprintf(outfile,
"%4d %4d %4d %4d %4d\n", elementnumber,
31212 neighbori[0], neighbori[1], neighbori[2], neighbori[3]);
31214 nlist[index++] = neighbori[0];
31215 nlist[index++] = neighbori[1];
31216 nlist[index++] = neighbori[2];
31217 nlist[index++] = neighbori[3];
31219 tetloop.tet = tetrahedrontraverse();
31224 fprintf(outfile,
"# Generated by %s\n", b->commandline);
31250 void tetgenmesh::outvoronoi(
tetgenio* out)
31252 FILE *outfile = NULL;
31253 char outfilename[FILENAMESIZE];
31256 arraypool *tetlist, *ptlist;
31257 triface tetloop, worktet, spintet, firsttet;
31258 point pt[4], ploop, neipt;
31259 REAL ccent[3], infvec[3], vec1[3], vec2[3], L;
31260 long ntets, faces, edges;
31261 int *indexarray, *fidxs, *eidxs;
31263 int vpointcount, vedgecount, vfacecount, tcount;
31264 int ishullvert, ishullface;
31265 int index, shift, end1, end2;
31272 strcpy(outfilename, b->outfilename);
31273 strcat(outfilename,
".v.node");
31278 printf(
"Writing %s.\n", outfilename);
31280 printf(
"Writing Voronoi vertices.\n");
31285 shift = (b->zeroindex ? 0 : in->firstnumber);
31292 indexarray =
new int[tetrahedrons->items * 10];
31297 tetrahedrons->traversalinit();
31298 tetloop.tet = alltetrahedrontraverse();
31299 while (tetloop.tet != NULL) {
31300 tetloop.tet[11] = (tetrahedron) &(indexarray[i * 10]);
31302 tetloop.tet = alltetrahedrontraverse();
31306 ntets = tetrahedrons->items - hullsize;
31308 faces = (4l * ntets + hullsize) / 2l;
31310 long vsize = points->items - dupverts - unuverts;
31311 if (b->weighted) vsize -= nonregularcount;
31313 edges = vsize + faces - ntets - 1;
31315 if (meshedges == 0l) {
31322 outfile = fopen(outfilename,
"w");
31323 if (outfile == (FILE *) NULL) {
31324 printf(
"File I/O Error: Cannot create file %s.\n", outfilename);
31325 terminatetetgen(
this, 3);
31328 fprintf(outfile,
"%ld 3 0 0\n", ntets);
31331 out->numberofvpoints = (int) ntets;
31332 out->vpointlist =
new REAL[out->numberofvpoints * 3];
31333 if (out->vpointlist == (REAL *) NULL) {
31334 terminatetetgen(
this, 1);
31339 tetrahedrons->traversalinit();
31340 tetloop.tet = tetrahedrontraverse();
31343 while (tetloop.tet != (tetrahedron *) NULL) {
31344 for (i = 0; i < 4; i++) {
31345 pt[i] = (point) tetloop.tet[4 + i];
31346 setpoint2tet(pt[i], encode(tetloop));
31349 orthosphere(pt[0], pt[1], pt[2], pt[3], pt[0][3], pt[1][3], pt[2][3],
31350 pt[3][3], ccent, NULL);
31352 circumsphere(pt[0], pt[1], pt[2], pt[3], ccent, NULL);
31355 fprintf(outfile,
"%4d %16.8e %16.8e %16.8e\n", vpointcount + shift,
31356 ccent[0], ccent[1], ccent[2]);
31358 out->vpointlist[index++] = ccent[0];
31359 out->vpointlist[index++] = ccent[1];
31360 out->vpointlist[index++] = ccent[2];
31362 setelemindex(tetloop.tet, vpointcount);
31364 tetloop.tet = tetrahedrontraverse();
31368 fprintf(outfile,
"# Generated by %s\n", b->commandline);
31374 strcpy(outfilename, b->outfilename);
31375 strcat(outfilename,
".v.edge");
31380 printf(
"Writing %s.\n", outfilename);
31382 printf(
"Writing Voronoi edges.\n");
31387 outfile = fopen(outfilename,
"w");
31388 if (outfile == (FILE *) NULL) {
31389 printf(
"File I/O Error: Cannot create file %s.\n", outfilename);
31390 terminatetetgen(
this, 3);
31393 fprintf(outfile,
"%ld 0\n", faces);
31396 out->numberofvedges = (int) faces;
31401 tetrahedrons->traversalinit();
31402 tetloop.tet = tetrahedrontraverse();
31405 while (tetloop.tet != (tetrahedron *) NULL) {
31409 end1 = elemindex(tetloop.tet);
31410 for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
31411 fsym(tetloop, worktet);
31412 if (ishulltet(worktet) ||
31413 (elemindex(tetloop.tet) < elemindex(worktet.tet))) {
31416 fprintf(outfile,
"%4d %4d", vedgecount + shift, end1 + shift);
31418 vedge = &(out->vedgelist[index++]);
31419 vedge->v1 = end1 + shift;
31421 if (!ishulltet(worktet)) {
31422 end2 = elemindex(worktet.tet);
31429 pt[0] = dest(worktet);
31430 pt[1] = org(worktet);
31431 pt[2] = apex(worktet);
31432 for (j = 0; j < 3; j++) vec1[j] = pt[1][j] - pt[0][j];
31433 for (j = 0; j < 3; j++) vec2[j] = pt[2][j] - pt[0][j];
31434 cross(vec1, vec2, infvec);
31436 L = sqrt(infvec[0] * infvec[0] + infvec[1] * infvec[1]
31437 + infvec[2] * infvec[2]);
31438 if (L > 0)
for (j = 0; j < 3; j++) infvec[j] /= L;
31440 fprintf(outfile,
" -1");
31441 fprintf(outfile,
" %g %g %g\n", infvec[0], infvec[1], infvec[2]);
31444 vedge->vnormal[0] = infvec[0];
31445 vedge->vnormal[1] = infvec[1];
31446 vedge->vnormal[2] = infvec[2];
31450 fprintf(outfile,
" %4d\n", end2 + shift);
31452 vedge->v2 = end2 + shift;
31453 vedge->vnormal[0] = 0.0;
31454 vedge->vnormal[1] = 0.0;
31455 vedge->vnormal[2] = 0.0;
31459 fidxs = (
int *) (tetloop.tet[11]);
31460 fidxs[tetloop.ver] = vedgecount;
31461 fidxs = (
int *) (worktet.tet[11]);
31462 fidxs[worktet.ver & 3] = vedgecount;
31466 tetloop.tet = tetrahedrontraverse();
31470 fprintf(outfile,
"# Generated by %s\n", b->commandline);
31476 strcpy(outfilename, b->outfilename);
31477 strcat(outfilename,
".v.face");
31482 printf(
"Writing %s.\n", outfilename);
31484 printf(
"Writing Voronoi faces.\n");
31489 outfile = fopen(outfilename,
"w");
31490 if (outfile == (FILE *) NULL) {
31491 printf(
"File I/O Error: Cannot create file %s.\n", outfilename);
31492 terminatetetgen(
this, 3);
31495 fprintf(outfile,
"%ld 0\n", edges);
31497 out->numberofvfacets = edges;
31500 terminatetetgen(
this, 1);
31505 tetrahedrons->traversalinit();
31506 tetloop.tet = tetrahedrontraverse();
31508 while (tetloop.tet != (tetrahedron *) NULL) {
31512 worktet.tet = tetloop.tet;
31513 for (i = 0; i < 6; i++) {
31514 worktet.ver = edge2ver[i];
31519 firsttet = worktet;
31523 fnextself(spintet);
31524 if (spintet.tet == worktet.tet)
break;
31525 if (!ishulltet(spintet)) {
31526 if (elemindex(spintet.tet) < elemindex(worktet.tet))
break;
31529 if (apex(spintet) == dummypoint) {
31531 fnext(spintet, firsttet);
31535 if (spintet.tet == worktet.tet) {
31537 pt[0] = org(worktet);
31538 pt[1] = dest(worktet);
31539 end1 = pointmark(pt[0]) - in->firstnumber;
31540 end2 = pointmark(pt[1]) - in->firstnumber;
31542 fprintf(outfile,
"%4d %4d %4d %-2d ", vfacecount + shift,
31543 end1 + shift, end2 + shift, tcount);
31545 vfacet = &(out->vfacetlist[vfacecount]);
31546 vfacet->c1 = end1 + shift;
31547 vfacet->c2 = end2 + shift;
31548 vfacet->elist =
new int[tcount + 1];
31549 vfacet->elist[0] = tcount;
31553 spintet = firsttet;
31555 fidxs = (
int *) (spintet.tet[11]);
31556 if (apex(spintet) != dummypoint) {
31557 vedgecount = fidxs[spintet.ver & 3];
31563 fprintf(outfile,
" %d", !ishullface ? (vedgecount + shift) : -1);
31565 vfacet->elist[index++] = !ishullface ? (vedgecount + shift) : -1;
31568 eidxs = &(fidxs[4]);
31569 eidxs[ver2edge[spintet.ver]] = vfacecount;
31571 fnextself(spintet);
31572 if (spintet.tet == firsttet.tet)
break;
31575 fprintf(outfile,
"\n");
31580 tetloop.tet = tetrahedrontraverse();
31584 fprintf(outfile,
"# Generated by %s\n", b->commandline);
31590 strcpy(outfilename, b->outfilename);
31591 strcat(outfilename,
".v.cell");
31596 printf(
"Writing %s.\n", outfilename);
31598 printf(
"Writing Voronoi cells.\n");
31603 outfile = fopen(outfilename,
"w");
31604 if (outfile == (FILE *) NULL) {
31605 printf(
"File I/O Error: Cannot create file %s.\n", outfilename);
31606 terminatetetgen(
this, 3);
31609 fprintf(outfile,
"%ld\n", points->items - unuverts - dupverts);
31611 out->numberofvcells = points->items - unuverts - dupverts;
31612 out->vcelllist =
new int*[out->numberofvcells];
31613 if (out->vcelllist == (
int **) NULL) {
31614 terminatetetgen(
this, 1);
31619 tetlist = cavetetlist;
31620 ptlist = cavetetvertlist;
31621 points->traversalinit();
31622 ploop = pointtraverse();
31624 while (ploop != (point) NULL) {
31625 if ((pointtype(ploop) != UNUSEDVERTEX) &&
31626 (pointtype(ploop) != DUPLICATEDVERTEX) &&
31627 (pointtype(ploop) != NREGULARVERTEX)) {
31628 getvertexstar(1, ploop, tetlist, ptlist, NULL);
31631 for (i = 0; i < ptlist->objects; i++) {
31632 neipt = * (point *) fastlookup(ptlist, i);
31633 if (neipt != dummypoint) {
31639 tcount = (int) ptlist->objects;
31641 fprintf(outfile,
"%4d %-2d ", vpointcount + shift, tcount);
31643 arraysize = tcount;
31645 out->vcelllist[vpointcount] =
vertarray;
31650 for (i = 0; i < tetlist->objects; i++) {
31651 worktet = * (triface *) fastlookup(tetlist, i);
31653 for (j = 0; j < 3; j++) {
31654 neipt = org(worktet);
31656 if (neipt != dummypoint) {
31657 if (pinfected(neipt)) {
31661 esym(worktet, spintet);
31662 enextself(spintet);
31664 eidxs = (
int *) spintet.tet[11];
31665 vfacecount = eidxs[4 + ver2edge[spintet.ver]];
31667 fprintf(outfile,
" %d", vfacecount + shift);
31669 vertarray[index++] = vfacecount + shift;
31673 enextself(worktet);
31679 fprintf(outfile,
" -1");
31685 fprintf(outfile,
"\n");
31687 tetlist->restart();
31691 ploop = pointtraverse();
31695 delete [] indexarray;
31698 fprintf(outfile,
"# Generated by %s\n", b->commandline);
31714 void tetgenmesh::outsmesh(
char* smfilename)
31717 char nodfilename[FILENAMESIZE];
31718 char smefilename[FILENAMESIZE];
31721 int firstindex, shift;
31726 if (smfilename != (
char *) NULL && smfilename[0] !=
'\0') {
31727 strcpy(smefilename, smfilename);
31728 }
else if (b->outfilename[0] !=
'\0') {
31729 strcpy(smefilename, b->outfilename);
31731 strcpy(smefilename,
"unnamed");
31733 strcpy(nodfilename, smefilename);
31734 strcat(smefilename,
".smesh");
31735 strcat(nodfilename,
".node");
31738 printf(
"Writing %s.\n", smefilename);
31740 outfile = fopen(smefilename,
"w");
31741 if (outfile == (FILE *) NULL) {
31742 printf(
"File I/O Error: Cannot create file %s.\n", smefilename);
31747 firstindex = b->zeroindex ? 0 : in->firstnumber;
31749 if ((in->firstnumber == 1) && (firstindex == 0)) {
31753 fprintf(outfile,
"# %s. TetGen's input file.\n", smefilename);
31754 fprintf(outfile,
"\n# part 1: node list.\n");
31755 fprintf(outfile,
"0 3 0 0 # nodes are found in %s.\n", nodfilename);
31758 bmark = !b->nobound && (in->facetmarkerlist || in->trifacemarkerlist);
31760 fprintf(outfile,
"\n# part 2: facet list.\n");
31762 fprintf(outfile,
"%ld %d\n", subfaces->items, bmark);
31764 subfaces->traversalinit();
31765 faceloop.sh = shellfacetraverse(subfaces);
31766 while (faceloop.sh != (shellface *) NULL) {
31767 p1 = sorg(faceloop);
31768 p2 = sdest(faceloop);
31769 p3 = sapex(faceloop);
31771 marker = shellmark(faceloop);
31773 fprintf(outfile,
"3 %4d %4d %4d", pointmark(p1) - shift,
31774 pointmark(p2) - shift, pointmark(p3) - shift);
31776 fprintf(outfile,
" %d", marker);
31778 fprintf(outfile,
"\n");
31779 faceloop.sh = shellfacetraverse(subfaces);
31783 fprintf(outfile,
"\n# part 3: hole list.\n");
31784 fprintf(outfile,
"%d\n", in->numberofholes);
31785 for (i = 0; i < in->numberofholes; i++) {
31786 fprintf(outfile,
"%d %g %g %g\n", i + in->firstnumber,
31787 in->holelist[i * 3], in->holelist[i * 3 + 1],
31788 in->holelist[i * 3 + 2]);
31792 fprintf(outfile,
"\n# part 4: region list.\n");
31793 fprintf(outfile,
"%d\n", in->numberofregions);
31794 for (i = 0; i < in->numberofregions; i++) {
31795 fprintf(outfile,
"%d %g %g %g %d %g\n", i + in->firstnumber,
31796 in->regionlist[i * 5], in->regionlist[i * 5 + 1],
31797 in->regionlist[i * 5 + 2], (
int) in->regionlist[i * 5 + 3],
31798 in->regionlist[i * 5 + 4]);
31801 fprintf(outfile,
"# Generated by %s\n", b->commandline);
31816 void tetgenmesh::outmesh2medit(
char* mfilename)
31819 char mefilename[FILENAMESIZE];
31820 tetrahedron* tetptr;
31821 triface tface, tsymface;
31822 face segloop, checkmark;
31823 point ptloop, p1, p2, p3, p4;
31829 if (mfilename != (
char *) NULL && mfilename[0] !=
'\0') {
31830 strcpy(mefilename, mfilename);
31831 }
else if (b->outfilename[0] !=
'\0') {
31832 strcpy(mefilename, b->outfilename);
31834 strcpy(mefilename,
"unnamed");
31836 strcat(mefilename,
".mesh");
31839 printf(
"Writing %s.\n", mefilename);
31841 outfile = fopen(mefilename,
"w");
31842 if (outfile == (FILE *) NULL) {
31843 printf(
"File I/O Error: Cannot create file %s.\n", mefilename);
31847 fprintf(outfile,
"MeshVersionFormatted 1\n");
31848 fprintf(outfile,
"\n");
31849 fprintf(outfile,
"Dimension\n");
31850 fprintf(outfile,
"3\n");
31851 fprintf(outfile,
"\n");
31853 fprintf(outfile,
"\n# Set of mesh vertices\n");
31854 fprintf(outfile,
"Vertices\n");
31855 fprintf(outfile,
"%ld\n", points->items);
31857 points->traversalinit();
31858 ptloop = pointtraverse();
31860 while (ptloop != (point) NULL) {
31862 fprintf(outfile,
"%.17g %.17g %.17g", ptloop[0], ptloop[1], ptloop[2]);
31863 if (in->numberofpointattributes > 0) {
31865 fprintf(outfile,
" %.17g\n", ptloop[3]);
31867 fprintf(outfile,
" 0\n");
31869 setpointmark(ptloop, pointnumber);
31870 ptloop = pointtraverse();
31875 ntets = tetrahedrons->items - hullsize;
31876 faces = (ntets * 4l + hullsize) / 2l;
31878 fprintf(outfile,
"\n# Set of Triangles\n");
31879 fprintf(outfile,
"Triangles\n");
31880 fprintf(outfile,
"%ld\n", faces);
31882 tetrahedrons->traversalinit();
31883 tface.tet = tetrahedrontraverse();
31884 while (tface.tet != (tetrahedron *) NULL) {
31885 for (tface.ver = 0; tface.ver < 4; tface.ver ++) {
31886 fsym(tface, tsymface);
31887 if (ishulltet(tsymface) ||
31888 (elemindex(tface.tet) < elemindex(tsymface.tet))) {
31892 fprintf(outfile,
"%5d %5d %5d",
31893 pointmark(p1), pointmark(p2), pointmark(p3));
31895 tspivot(tface, checkmark);
31896 if (checkmark.sh == NULL) {
31899 marker = shellmark(checkmark);
31901 fprintf(outfile,
" %d\n", marker);
31904 tface.tet = tetrahedrontraverse();
31907 fprintf(outfile,
"\n# Set of Tetrahedra\n");
31908 fprintf(outfile,
"Tetrahedra\n");
31909 fprintf(outfile,
"%ld\n", ntets);
31911 tetrahedrons->traversalinit();
31912 tetptr = tetrahedrontraverse();
31913 while (tetptr != (tetrahedron *) NULL) {
31914 if (!b->reversetetori) {
31915 p1 = (point) tetptr[4];
31916 p2 = (point) tetptr[5];
31918 p1 = (point) tetptr[5];
31919 p2 = (point) tetptr[4];
31921 p3 = (point) tetptr[6];
31922 p4 = (point) tetptr[7];
31923 fprintf(outfile,
"%5d %5d %5d %5d",
31924 pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
31925 if (numelemattrib > 0) {
31926 fprintf(outfile,
" %.17g", elemattribute(tetptr, 0));
31928 fprintf(outfile,
" 0");
31930 fprintf(outfile,
"\n");
31931 tetptr = tetrahedrontraverse();
31934 fprintf(outfile,
"\nCorners\n");
31935 fprintf(outfile,
"%d\n", in->numberofpoints);
31937 for (i = 0; i < in->numberofpoints; i++) {
31938 fprintf(outfile,
"%4d\n", i + 1);
31941 if (b->plc || b->refine) {
31942 fprintf(outfile,
"\nEdges\n");
31943 fprintf(outfile,
"%ld\n", subsegs->items);
31945 subsegs->traversalinit();
31946 segloop.sh = shellfacetraverse(subsegs);
31947 while (segloop.sh != (shellface *) NULL) {
31948 p1 = sorg(segloop);
31949 p2 = sdest(segloop);
31950 fprintf(outfile,
"%5d %5d", pointmark(p1), pointmark(p2));
31951 marker = shellmark(segloop);
31952 fprintf(outfile,
" %d\n", marker);
31953 segloop.sh = shellfacetraverse(subsegs);
31957 fprintf(outfile,
"\nEnd\n");
31973 void tetgenmesh::outmesh2vtk(
char* ofilename)
31976 char vtkfilename[FILENAMESIZE];
31977 point pointloop, p1, p2, p3, p4;
31980 int n1, n2, n3, n4;
31984 if (b->order == 2) {
31985 printf(
" Write VTK not implemented for order 2 elements \n");
31989 int NEL = tetrahedrons->items - hullsize;
31990 int NN = points->items;
31992 if (ofilename != (
char *) NULL && ofilename[0] !=
'\0') {
31993 strcpy(vtkfilename, ofilename);
31994 }
else if (b->outfilename[0] !=
'\0') {
31995 strcpy(vtkfilename, b->outfilename);
31997 strcpy(vtkfilename,
"unnamed");
31999 strcat(vtkfilename,
".vtk");
32002 printf(
"Writing %s.\n", vtkfilename);
32004 outfile = fopen(vtkfilename,
"w");
32005 if (outfile == (FILE *) NULL) {
32006 printf(
"File I/O Error: Cannot create file %s.\n", vtkfilename);
32013 fprintf(outfile,
"# vtk DataFile Version 2.0\n");
32014 fprintf(outfile,
"Unstructured Grid\n");
32015 fprintf(outfile,
"ASCII\n");
32016 fprintf(outfile,
"DATASET UNSTRUCTURED_GRID\n");
32017 fprintf(outfile,
"POINTS %d double\n", NN);
32019 points->traversalinit();
32020 pointloop = pointtraverse();
32021 for(
int id=0;
id<NN && pointloop != (point) NULL;
id++){
32025 fprintf(outfile,
"%.17g %.17g %.17g\n", x, y, z);
32026 pointloop = pointtraverse();
32028 fprintf(outfile,
"\n");
32030 fprintf(outfile,
"CELLS %d %d\n", NEL, NEL*(4+1));
32033 tetrahedrons->traversalinit();
32034 tptr = tetrahedrontraverse();
32036 while (tptr != (tetrahedron *) NULL) {
32037 if (!b->reversetetori) {
32038 p1 = (point) tptr[4];
32039 p2 = (point) tptr[5];
32041 p1 = (point) tptr[5];
32042 p2 = (point) tptr[4];
32044 p3 = (point) tptr[6];
32045 p4 = (point) tptr[7];
32046 n1 = pointmark(p1) - in->firstnumber;
32047 n2 = pointmark(p2) - in->firstnumber;
32048 n3 = pointmark(p3) - in->firstnumber;
32049 n4 = pointmark(p4) - in->firstnumber;
32050 fprintf(outfile,
"%d %4d %4d %4d %4d\n", nnodes, n1, n2, n3, n4);
32051 tptr = tetrahedrontraverse();
32053 fprintf(outfile,
"\n");
32055 fprintf(outfile,
"CELL_TYPES %d\n", NEL);
32056 for(
int tid=0; tid<NEL; tid++){
32057 fprintf(outfile,
"%d\n", celltype);
32059 fprintf(outfile,
"\n");
32061 if (numelemattrib > 0) {
32063 fprintf(outfile,
"CELL_DATA %d\n", NEL);
32064 fprintf(outfile,
"SCALARS cell_scalars int 1\n");
32065 fprintf(outfile,
"LOOKUP_TABLE default\n");
32066 tetrahedrons->traversalinit();
32067 tptr = tetrahedrontraverse();
32068 while (tptr != (tetrahedron *) NULL) {
32069 fprintf(outfile,
"%d\n", (
int) elemattribute(tptr, numelemattrib - 1));
32070 tptr = tetrahedrontraverse();
32072 fprintf(outfile,
"\n");
32114 clock_t tv[12], ts[5];
32115 REAL cps = (REAL) CLOCKS_PER_SEC;
32123 if (b->metric && bgmin && (bgmin->numberofpoints > 0)) {
32129 m.initializepools();
32132 exactinit(b->verbose, b->noexact, b->nostaticfilter,
32133 m.xmax - m.xmin, m.ymax - m.ymin, m.zmax - m.zmin);
32138 m.reconstructmesh();
32140 m.incrementaldelaunay(ts[0]);
32147 printf(
"Mesh reconstruction seconds: %g\n", ((REAL)(tv[2]-tv[1])) / cps);
32149 printf(
"Delaunay seconds: %g\n", ((REAL)(tv[2]-tv[1])) / cps);
32151 printf(
" Point sorting seconds: %g\n", ((REAL)(ts[0]-tv[1])) / cps);
32157 if (b->plc && !b->refine) {
32163 printf(
"Surface mesh seconds: %g\n", ((REAL)(ts[0]-tv[2])) / cps);
32167 m.detectinterfaces();
32172 printf(
"Self-intersection seconds: %g\n", ((REAL)(ts[1]-ts[0])) / cps);
32176 if (m.subfaces->items > 0l) {
32178 m.outsubfaces(out);
32188 if ((b->metric) && (m.bgm != NULL)) {
32189 m.bgm->initializepools();
32190 m.bgm->transfernodes();
32191 m.bgm->reconstructmesh();
32196 printf(
"Background mesh reconstruct seconds: %g\n",
32197 ((REAL)(ts[0] - tv[3])) / cps);
32201 m.interpolatemeshsize();
32206 printf(
"Size interpolating seconds: %g\n",((REAL)(ts[1]-ts[0])) / cps);
32213 if (b->plc && !b->refine) {
32215 m.recoverboundary(ts[0]);
32217 m.constraineddelaunay(ts[0]);
32224 printf(
"Boundary recovery ");
32226 printf(
"Constrained Delaunay ");
32228 printf(
"seconds: %g\n", ((REAL)(ts[1] - tv[4])) / cps);
32230 printf(
" Segment recovery seconds: %g\n",((REAL)(ts[0]-tv[4]))/ cps);
32231 printf(
" Facet recovery seconds: %g\n", ((REAL)(ts[1]-ts[0])) / cps);
32240 printf(
"Exterior tets removal seconds: %g\n",((REAL)(ts[2]-ts[1]))/cps);
32244 if (m.subvertstack->objects > 0l) {
32245 m.suppresssteinerpoints();
32250 printf(
"Steiner suppression seconds: %g\n",
32251 ((REAL)(ts[3]-ts[2]))/cps);
32260 m.meshcoarsening();
32267 printf(
"Mesh coarsening seconds: %g\n", ((REAL)(tv[6] - tv[5])) / cps);
32271 if ((b->plc && b->nobisect) || b->coarsen) {
32272 m.recoverdelaunay();
32278 if ((b->plc && b->nobisect) || b->coarsen) {
32279 printf(
"Delaunay recovery seconds: %g\n", ((REAL)(tv[7] - tv[6]))/cps);
32283 if ((b->plc || b->refine) && b->insertaddpoints) {
32284 if ((addin != NULL) && (addin->numberofpoints > 0)) {
32285 m.insertconstrainedpoints(addin);
32292 if ((b->plc || b->refine) && b->insertaddpoints) {
32293 if ((addin != NULL) && (addin->numberofpoints > 0)) {
32294 printf(
"Constrained points seconds: %g\n", ((REAL)(tv[8]-tv[7]))/cps);
32300 m.delaunayrefinement();
32307 printf(
"Refinement seconds: %g\n", ((REAL)(tv[9] - tv[8])) / cps);
32311 if ((b->plc || b->refine) && (b->optlevel > 0)) {
32318 if ((b->plc || b->refine) && (b->optlevel > 0)) {
32319 printf(
"Optimization seconds: %g\n", ((REAL)(tv[10] - tv[9])) / cps);
32324 if (!b->nojettison && ((m.dupverts > 0) || (m.unuverts > 0)
32325 || (b->refine && (in->numberofcorners == 10)))) {
32329 if ((b->order == 2) && !b->convex) {
32338 out->firstnumber = in->firstnumber;
32339 out->mesh_dim = in->mesh_dim;
32342 if (b->nonodewritten || b->noiterationnum) {
32344 printf(
"NOT writing a .node file.\n");
32350 if (b->noelewritten) {
32352 printf(
"NOT writing an .ele file.\n");
32356 if (m.tetrahedrons->items > 0l) {
32357 m.outelements(out);
32361 if (b->nofacewritten) {
32363 printf(
"NOT writing an .face file.\n");
32367 if (m.tetrahedrons->items > 0l) {
32371 if (b->plc || b->refine) {
32372 if (m.subfaces->items > 0l) {
32373 m.outsubfaces(out);
32376 if (m.tetrahedrons->items > 0l) {
32377 m.outhullfaces(out);
32384 if (b->nofacewritten) {
32386 printf(
"NOT writing an .edge file.\n");
32392 if (b->plc || b->refine) {
32393 m.outsubsegments(out);
32398 if ((b->plc || b->refine) && b->metric) {
32402 if (!out && b->plc &&
32403 ((b->object == tetgenbehavior::OFF) ||
32404 (b->object == tetgenbehavior::PLY) ||
32405 (b->object == tetgenbehavior::STL))) {
32406 m.outsmesh(b->outfilename);
32409 if (!out && b->meditview) {
32410 m.outmesh2medit(b->outfilename);
32414 if (!out && b->vtkview) {
32415 m.outmesh2vtk(b->outfilename);
32419 m.outneighbors(out);
32430 printf(
"\nOutput seconds: %g\n", ((REAL)(tv[11] - tv[10])) / cps);
32431 printf(
"Total running seconds: %g\n", ((REAL)(tv[11] - tv[0])) / cps);
32436 if (b->plc || b->refine) {
32440 if (b->docheck > 1) {
32458 int main(
int argc,
char *argv[])
32460 #else // with TETLIBRARY 32471 #endif // not TETLIBRARY 32480 if (!b.parse_commandline(argc, argv)) {
32481 terminatetetgen(NULL, 10);
32486 if (!in.load_tetmesh(b.infilename, (
int) b.object)) {
32487 terminatetetgen(NULL, 10);
32490 if (!in.load_plc(b.infilename, (
int) b.object)) {
32491 terminatetetgen(NULL, 10);
32494 if (b.insertaddpoints) {
32496 addin.load_node(b.addinfilename);
32500 bgmin.load_tetmesh(b.bgmeshfilename, (
int) b.object);
32503 tetrahedralize(&b, &in, NULL, &addin, &bgmin);
32507 #else // with TETLIBRARY 32509 if (!b.parse_commandline(switches)) {
32510 terminatetetgen(NULL, 10);
32512 tetrahedralize(&b, in, out, addin, bgmin);
32514 #endif // not TETLIBRARY